I am trying to debug a function that gets executed with a webhook from a third party app. I am using ngrok as a proxy to relay the webhook to localhost.
If I disable all edge functions, all works fine. But once Deno is in the mix, any request coming from ngrok crashes, but making the same requests locally on localhost runs fine.
I was able to identify the specific line of code that’s causing the issue. The origin request sent by Ngrok contains both x-forwarded-proto and x-forwarded-for headers. These are stored as Netlify internal request headers in the EdgeRequest constructor and passed around all subsequent requests, and removed from the publicly readable headers property.
During fetchPassthrough function of function_chain.ts, line 98. a new PassthroughRequest is created, using the original request. The original request the following url: http://localhost:34965/. However, in the PassthroughRequest constructor, line 143, I found this:
// When running locally, we allow the client to specify the host and the
// protocol used for origin requests.
if (environment === “local”) {
url.host = req[internalsSymbol].forwardedHost ?? url.host;
url.protocol = req[internalsSymbol].forwardedProtocol
?${req[internalsSymbol].forwardedProtocol}:
: url.protocol;
}
This picks up the original forwardedProtocol from the origin request’s x-forwarded-proto header and changes the URL to https://localhost:34965/, which crashes.
When the request comes from the local browser and no x-forwarded headers are present, this doesn’t happen, fetchPassthrough and PassThroughRequest use http://localhost:34965/ and everything works fine.
The reason this seems like a bug is the original http request coming to Deno has the following forwarding headers:
x-forwarded-proto: https
x-forwarded-for: ::ffff:127.0.0.1
Then Netlify adds x-forwarded-host: localhost:34965, which gets used in the PassthroughRequest constructor in the snippet above. But it also looks for x-forwarded-proto, which was actually set by Ngrok and should have been reset to null.