Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate edge middleware to run reroute #12296

Open
wants to merge 53 commits into
base: main
Choose a base branch
from

Conversation

eltigerchino
Copy link
Member

@eltigerchino eltigerchino commented Jun 4, 2024

fixes #11879

This PR adds an edge middleware that runs reroute beforehand so that, when there are multiple functions, the correct one is invoked instead of not matching any function matchers.

The Vercel middleware uses the rewrite helper from @vercel/edge.

The Netlify middleware simply requires returning the new URL.

TODO

  • cleanup duplicated edge function generation code
  • docs
    - [ ] don't run reroute again in the split function that comes after the middleware
  • retain original URL via query params
    • apparently the Vercel edge middleware passes the original URL to the next function instead of the rewritten URL. So, we do need to run rewrite again after the middleware runs. In contrast, Netlify passes the rewritten URL back to the middleware then to the next function.
  • abstract implementation into an exported helper
  • netlify edge-functions-examples.netlify.app/example/rewrite
  • reliably import reroute hook from build output file when universal hooks file name is different

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@eltigerchino eltigerchino added the pkg:adapter-vercel Pertaining to the Vercel adapter label Jun 4, 2024
Copy link

changeset-bot bot commented Jun 4, 2024

🦋 Changeset detected

Latest commit: 9fcdfc1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@sveltejs/adapter-netlify Minor
@sveltejs/adapter-vercel Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@eltigerchino eltigerchino changed the title fix: use Vercel edge middleware if reroute hook exists and more than one function fix: use Vercel edge middleware to run reroute Jun 4, 2024
@dominikg
Copy link
Member

dominikg commented Jun 4, 2024

Should this be a bit more generic so that it can be used by other adapters too? or is the way route splitting works so adapter-specific that they all need a separate implementation?

@eltigerchino
Copy link
Member Author

eltigerchino commented Jun 4, 2024

Should this be a bit more generic so that it can be used by other adapters too? or is the way route splitting works so adapter-specific that they all need a separate implementation?

I think it's possible for the part where we need to import the reroute hook and get the rewritten URL. The rest seems more platform specific. Vercel uses a custom header in a Response while Netlify just requires a URL https://edge-functions-examples.netlify.app/example/rewrite . Not sure about other platforms.

CC: @LorisSigrist

@LorisSigrist
Copy link
Contributor

LorisSigrist commented Jun 5, 2024

Each Serverless provider is going to have a different way of rewriting the URL so that would certainly be adapter-specific.

Given that .sveltekit/output/server/chunks/hooks.js already contains a bundled, useable version of the hooks.js file I don't see a reason to move the bundling outside of the adapter right now. The bundling in the adapter basically just amounts to concatonating the platform-specific code with an already bundled hooks.js file, which is unlikely to go wrong.

There is some fragility since we're assuming that the bundled file will always be at that path, meaning that changes in sveltekit's build-output may break the adapters, but I don't think that warrants adding a shared implementation right now. We can always share it later if the need arises.

@LorisSigrist
Copy link
Contributor

don't run reroute again in the split function that comes after the middleware

The most straight forward solution here would probably be to have a x-sveltekit-rerouted-from header to signal that the reroute hook does not need to run again & what the original URL was.

add abstraction for kit adapter API?

Let's wait on this one for now, this can be added later if the need arises from other adapters. When I suggested that we might need to extend the adapter API I didn't know we could just access files from the output-directory directly.

@eltigerchino
Copy link
Member Author

eltigerchino commented Jun 5, 2024

added a naive implementation to support Netlify then realised the adapter only supports split for normal functions. Couldn't even find an existing issue to add split support for edge functions. I guess the Netlify demand and support isn't that strong.

@eltigerchino
Copy link
Member Author

eltigerchino commented Jun 5, 2024

don't run reroute again in the split function that comes after the middleware

The most straight forward solution here would probably be to have a x-sveltekit-rerouted-from header to signal that the reroute hook does not need to run again & what the original URL was.

I wish we could do this but I'm not sure if it's possible on Netlify which only takes a URL object when rewriting and doesn't allow setting the headers like Vercel does (unless we decide to kick netlify to the curb and go ahead with the header implementation)

EDIT: maybe we can add the header in the serverless functions if split is enabled

@LorisSigrist
Copy link
Contributor

LorisSigrist commented Jun 6, 2024

maybe we can add the header in the serverless functions if split is enabled

That would be ideal

As a fallback we could go with a searchParam instead of a header, that should work everywhere.

@dominikg
Copy link
Member

dominikg commented Jun 6, 2024

what is the worst that would happen? that reroute is called again when the rerouted request hits the function?
If it is a fast sync function with stable result that shouldn't matter much, an early exit would be a small optimization.

Implementing it as a query param wouldn't really work unless the param is stripped again before it ever reaches the user. We must not mess with the presence or order in the querystring in any way, otherwise its going to break existing or future apps.

Even a custom header could be problematic in cases where headers are validated, but that also requires a change to the reroute signature. To introduce this in a non-breaking way would mean that you'll have to use return type like string | {url: string, more: boolean,stuff: string,here: any} and possibly also add new props to the input arg.

@LorisSigrist
Copy link
Contributor

Dominik is right

We have an error in our thinking. @eltigerchino and I assumed that the second reroute would be run on the already rerouted URL, but that's not actually the case. If it gets run again in the function then it gets run on the original URL and produce the same result. I just tested this in a deployment & it works as expected. We don't actually need to do the header/searchParam dance.

@eltigerchino
Copy link
Member Author

Updated the PR to include the same reroute fixes from #13092 in the Vercel and Netlify middleware functions

@eltigerchino eltigerchino marked this pull request as draft January 22, 2025 07:26
@eltigerchino eltigerchino marked this pull request as ready for review January 23, 2025 10:43
@eltigerchino
Copy link
Member Author

eltigerchino commented Jan 23, 2025

There's currently an issue with Vercel rewrites discarding the SvelteKit form action in the URL because the query parameter doesn't have a value vercel/vercel#12902

@eltigerchino eltigerchino marked this pull request as draft January 24, 2025 04:25
@eltigerchino eltigerchino marked this pull request as ready for review January 24, 2025 05:22
packages/adapter-netlify/index.js Outdated Show resolved Hide resolved
packages/adapter-vercel/index.js Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:adapter-netlify pkg:adapter-vercel Pertaining to the Vercel adapter
Projects
None yet
Development

Successfully merging this pull request may close these issues.

reroute hook breaks when deployed on Vercel if the app is deployed as multiple functions
7 participants