-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Using fetch to proxy resources fails with net::ERR_CONTENT_DECODING_FAILED error #12197
Comments
I faced the same problem some times ago and from my research is not an issue with sveltekit. The problem should be that the moment you fetch something in node it will be decoded with the So the response that you are returning to the browser is not exactly the same request, because node already decoded the body. But since the A better solution then this export async function GET() {
const resp = await fetch('https://en.wikipedia.org/wiki/Main_Page');
const t = await resp.text();
return new Response(t);
} should be this export async function GET() {
const resp = await fetch('https://en.wikipedia.org/wiki/Main_Page');
// copy the response headers over
const headers = new Headers(response.headers);
// delete content-encoding.
headers.delete('content-encoding');
return new Response(response.body, {
headers,
status: response.status,
statusText: response.statusText,
});
} |
Thank you for replying @paoloricciuti! Creating new headers works. I had tried to modify the headers from the response but had an error saying that the headers are immutable. I guess it makes sense now, can't modify headers from a response. When I tried your solution it worked for my local development (Vite with HTTPS), but did not work when deployed (node-adapter with HTTPS). I was getting the following error export async function GET() {
const resp = await fetch('https://en.wikipedia.org/wiki/Main_Page');
// copy the response headers over
const headers = new Headers(resp.headers);
headers.delete('content-encoding');
headers.delete('content-length');
return new Response(resp.body, {
headers,
status: resp.status,
statusText: resp.statusText,
});
} I understand the root cause regarding node decoding the compressed response, but I was wondering if this isn't something that could be fixed. From what I understand, fetch from SvelteKit isn't exactly the same as the native fetch web API, so perhaps this decoding can be avoided. Perhaps proxying isn't something SvelteKit needs to do well, in many cases the proxy can be implemented before a request gets to SvelteKit. Many web servers support this:
In my case this application is deployed behind an Application Load Balancer on AWS, which doesn't support reverse proxying. The best case scenario for me would be that adapter-node supports this, like adapter-vercel does. |
I just ran into this too, and I would argue that it is a problem with SvelteKit, but it's subtle. The But there's a weird inconsistency: If a response has However, SvelteKit does not implement symmetric logic on the outgoing path. If your application returns a This means that a server-side handler function that does Cloudflare Workers -- of which I'm the lead engineer -- actually realized this very early on, and implemented a solution: When returning a I'm not sure if SvelteKit can implement the same round-trip optimization (it would require reaching into |
Note this is specifically a problem in the Node adapter, probably in the kit/packages/kit/src/exports/node/index.js Line 124 in afd227c
When running on Cloudflare Workers, I think SvelteKit will actually get automatic compression behavior from the platform (just based on looking at the code, haven't tested yet). |
Nope I had this problem with cloud flare too and that's why I've implemented the fix I sent above
I think SvelteKit just wrap the fetch provided by the platform is used on...I think compressing the body at the framework level is the wrong place. This should probably be fixed in undici or whichever implementation of fetch the platform is using. |
Did you actually see it when running in production, or only in local dev? Because local dev for SvelteKit apps uses Node even when you are targeting Cloudflare for deployment.
The problem isn't in fetch()/undici, it's in the server-side handling. This isn't based on any framework, the coed is in SvelteKit, |
I remember having this problem in production but I might be wrong. The server side handling you linked to is only relative to node tho right? |
Right -- but again, it's also the code used in local dev when targeting Cloudflare, at least for now. (We (Workers team) are working towards getting vite to run workerd under the hood!) The Cloudflare code here appears to just return the
The Cloudflare Workers Runtime will compress the response body in this case (or keep it compressed, if proxying). |
Oh ok now i get it...fetch will decode the body only if the body it's used which is what adapter node is doing in |
No no, (And also, there is an optimization in Cloudflare Workers where it can detect when you are doing a round trip, and skip the round trip, but that's invisible...) |
Describe the bug
With 3rd party cookies soon to be blocked for authentication with Firebase, I was trying to create a hook to proxy the requests to Firebase as described here. It's simple to implement, but it leads to errors on the client side (Chrome in my case). Looking at the Network tab in Chrome Dev Tools shows an error in the "Status" column:
(failed)net::ERR_CONTENT_DECODING_FAILED
.I added some debugging info to understand the problem and found a mismatch between the size of the request as reported by Chrome Dev Tools vs the
Content-Length
header in the response to the proxied request.I think that what is happening is Sveltekit returns the HTTP response body as-is (compressed with gzip), but does not return the associated
Content-Encoding: gzip
header. Sveltekit does not pass any of the headers from the proxied response Perhaps this is intentional, but I think this is what's causing this issue.The workaround is to decode the response and create a new one, but this is a little annoying to do because some of the headers may need to be added back. For example in the case of Firebase, the workaround would not work until the 'Content-Type' header was added, the Firebase library could would reject the response without it (no reported error, making it difficult to understand). And it is slower too.
It might be worth to add that I wish there was a better way to proxy these requests instead of doing it in code. I know there is a way with the Vercel adapter using
rewrites
, and in local development vite can do it, but there is no such feature with node-adapter. If node-adapter had such a feature, I think it'd be more convenient than proxying with a hook. That could be a feature request ticket, but I think the issue described above is a bug.Reproduction
In any Sveltekit app, add a
/wiki
route with the following code:When using the code as is, the error will show in the status column of the network tab in Chrome Dev Tools. Using the commented out code works and the raw HTML will show on the page.
Logs
No response
System Info
Severity
serious, but I can work around it
Additional Information
No response
The text was updated successfully, but these errors were encountered: