vercel-community / rust

🦀 Rust runtime for ▲ Vercel Serverless Functions
https://rust-runtime.vercel.app
MIT License
845 stars 49 forks source link

Inconsistent `request.uri()` Behaviour in Dynamic Catch-All Routes #126

Open elcharitas opened 1 year ago

elcharitas commented 1 year ago

Problem Description: I am currently implementing a catch-all route in my project using this runtime. Within the handler for this catch-all route, I need to access the request URI using request.uri().

Issue Details:

// api/[...all].rs
use vercel_runtime::{run, Body, Error, Request, Response};

#[tokio::main]
async fn main() -> Result<(), Error> {
    run(handler).await
}

pub async fn handler(req: Request) -> Result<Response<Body>, Error> {
    println!("request.uri, {}", request.uri()); // prints /hello then /api/[...all]
}

This behavior is unexpected and inconsistent, as I would expect request.uri() to consistently return the path of the current request. I have reviewed my vercel configuration and am confident that it's not causing this issue. Here's my vercel.json JIC.

{
  "functions": {
    "api/**/*.rs": {
      "runtime": "vercel-rust@4.0.6"
    }
  },
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/api/$1"
    }
  ],
  "redirects": [
    {
      "source": "/",
      "destination": "/home",
      "statusCode": 301
    }
  ]
}

Steps to Reproduce:

  1. Create a catch-all route using the exact snippet above.
  2. Observe the value returned by request.uri().
  3. Refresh the page or navigate to a different route.
  4. Again, observe the value returned by request.uri(), which may now be unexpected.

Expected Behavior: request.uri() should consistently return the correct path for the current request, regardless of how many times the page is refreshed or navigated.

Environment:

I appreciate any insights or suggestions on resolving this issue. Thank you!

elcharitas commented 12 months ago

[UPDATE]

It seems the issue stems from lack of support for both rewrites and redirects with functions. Why? I have another sample where I used this simple vercel config and which works perfectly well:

{
  "functions": {
    "api/**/*.rs": {
      "runtime": "vercel-rust@4.0.6"
    }
  },
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/api/$1"
    }
  ]
}

This means this issue relates to #121 except, I'm not making use of the bundling api

elcharitas commented 10 months ago

Further investigation shows that the issue described above has nothing to do with vercel.json or the rewrites config. It turns out the vercel rust runtime router is the best candidate to be held responsible for this bug as the issue totally disappears when an optional catch all route is created.

For anyone who may not be aware, there are two possible catch all routes file names which this runtime supports:

Until this issue is fixed (I may open a PR if I have the time), if you're experiencing this same issue, you can switch to making use of an optional catch all route which is more friendly IMO 😅