sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.51k stars 1.9k forks source link

Why is `__vdpl` cookie used for Skew Protection in Vercel instead of `x-deployment-id` header? #12592

Open MathiasWP opened 1 month ago

MathiasWP commented 1 month ago

Describe the problem

We're trying to understand why our app multiple times a day report the Failed to fetch dynamically imported module issue to Sentry.

It seems that this is caused by the user opening a new version of the app in a new tab, which is documented on SvelteKit docs:

Cookie-based skew protection comes with one caveat: if a user has multiple versions of your app open in multiple tabs, requests from older versions will be routed to the newer one, meaning they will fall back to SvelteKit's built-in skew protection.

I may be understanding this wrong, but wouldn't the x-deployment-id header make it so different application versions in different tabs would not be affected by the new cookie that is set? Instead of setting the cookie across all app versions, wouldn't each application be able to use the separate deployment ID's in the header from the server its connected to?

Describe the proposed solution

Using x-deployment-id header instead of __vdpl cookie.

Alternatives considered

SvelteKits internal Skew Protection will reload the page which "solves" the error, but why not let the application keep working with Vercel's Skew protection if it's enabled?

Importance

would make my life easier

Additional Information

No response

eltigerchino commented 1 month ago

cc: @Rich-Harris @dummdidumm

Conduitry commented 1 month ago

Presumably because it was easier to set the cookie once and have SK's and the browser's automatic cookie handling take over. I don't know what setting this header on every request looks like. We'd need new hooks in SK to make that happen it feels like.

MathiasWP commented 1 month ago

Presumably because it was easier to set the cookie once and have SK's and the browser's automatic cookie handling take over. I don't know what setting this header on every request looks like. We'd need new hooks in SK to make that happen it feels like.

Can this be done in the adapter? I don't know how the adapter and routes fully work, but would it be possible to add a route that has src: '/.*' and setting 'x-deployment-id': process.env.VERCEL_DEPLOYMENT_ID in the header?

eltigerchino commented 1 month ago

Presumably because it was easier to set the cookie once and have SK's and the browser's automatic cookie handling take over. I don't know what setting this header on every request looks like. We'd need new hooks in SK to make that happen it feels like.

Can this be done in the adapter? I don't know how the adapter and routes fully work, but would it be possible to add a route that has src: '/.*' and setting 'x-deployment-id': process.env.VERCEL_DEPLOYMENT_ID in the header?

Sounds like what the generated vercel static config is suppose to do. ~I’m not sure if~ this only applies to static asset requests ~or also requests that hit serverless functions~ https://github.com/sveltejs/kit/blob/761b8afd33f45e6b9cf0be1fb3933213d4542b49/packages/adapter-vercel/index.js#L499

Conduitry commented 1 month ago

But we'd also need to inject that header into all requests made from the browser as well, right? That's more the part I'm concerned about. I don't think we have a mechanism to do that, and it's requests from the browser that are the primary concern in preventing version skew.

MathiasWP commented 1 month ago

But we'd also need to inject that header into all requests made from the browser as well, right? That's more the part I'm concerned about. I don't think we have a mechanism to do that, and it's requests from the browser that are the primary concern in preventing version skew.

If that's the case, could a Service Worker achieve this behaviour? Could the service-worker inject the x-deployment-id header via the fetch event in the ServiceWorkerGlobalScope ?

MathiasWP commented 1 month ago

Would it be possible to avoid injecting the header from the browser by instead adding the x-deployment-id in a middleware on the server? It doesn't matter where the header was set as long as it is present on the request before being handled, right? @Conduitry @eltigerchino

Conduitry commented 1 month ago

No, we can't inject the header later. We need to know what version the browser has. That's the whole point of skew protection.

eltigerchino commented 1 month ago

But we'd also need to inject that header into all requests made from the browser as well, right? That's more the part I'm concerned about. I don't think we have a mechanism to do that, and it's requests from the browser that are the primary concern in preventing version skew.

If that's the case, could a Service Worker achieve this behaviour? Could the service-worker inject the x-deployment-id header via the fetch event in the ServiceWorkerGlobalScope ?

I think it's worth experimenting with this. But then we'd also need a way for the adapter to add the service worker registration script.

MathiasWP commented 1 month ago

No, we can't inject the header later. We need to know what version the browser has. That's the whole point of skew protection.

True... i kinda forgot how servers work

MathiasWP commented 1 month ago

But we'd also need to inject that header into all requests made from the browser as well, right? That's more the part I'm concerned about. I don't think we have a mechanism to do that, and it's requests from the browser that are the primary concern in preventing version skew.

If that's the case, could a Service Worker achieve this behaviour? Could the service-worker inject the x-deployment-id header via the fetch event in the ServiceWorkerGlobalScope ?

I think it's worth experimenting with this. But then we'd also need a way for the adapter to add the service worker registration script.

I tried to experiment with no luck, but i have a almost no experience with Service Workers.

There should be ways to make the script appear in the final application if the adapter is present in the svelte.config.js file, right? I have no strong opinions on how, but it sounds like a solvable task.