Redirect origin response modified by Netlify Proxy

Hello,

I’ve encountered a problem with Netlify Proxy when Origin Server returns a 303 See Other response code.
In short: When I execute a query containing a query string, it is added to the Location header returned from the origin server and sent to the client modified.

Minimal working example proxies all requests to httpbin.
Source code is available on https://github.com/kubasaw/netlify-redirect
Netlify deploy is available on https://wonderful-selkie-849613.netlify.app/

netlify.toml content:

[[redirects]]
from = "/*"
to = "http://httpbin.org/:splat"
status = 200

Steps to reproduce:

  1. Call https://wonderful-selkie-849613.netlify.app/redirect-to?url=http://example.com&status_code=303

This call to httpbin should redirect client to http://example.com with HTTP 303 Status Code. Instead of it, user is redirected to http://example.com/?url=http://example.com&status_code=303

Moreover, this behavior is inconsistent with netlify-cli. If the development server is running on the local machine, the response is correct:

Similar problem is described here:
Reverse proxy with redirects is preserving query parameters on 302 response but was not answered.

Is there a chance this could be fixed? Alternatively, is it possible for the netlify-cli to work as intended in a production environment?

This isn’t a bug. Netlify attempts to preserve the query parameters that were passed:

While that talks about 301/302, I think it applies to all 3xx redirects.

The CLI thing could be a bug and should be reported on the CLI repo.

I think, Netlify should reconsider if it is expected. At the moment, netlify-cli seems to be doing the right thing i.e. pass through query parameters from client request to the origin server.
Netlify Proxy pass through query parameters from client request to the origin server and additionally append query parameters from client request to origin response Location header.

It makes no greater sense: when you call https://wonderful-selkie-849613.netlify.app/redirect-to?url=https%3A%2F%2Fexample.com%2F%3Furl%3Dexample2.com&status_code=303, origin server response Location header contains url=example2.com query param only, so why status_code request parameter is not preserved? There is no conflict with query params naming.

At the moment, if Origin server returns 3xx Location with any query param, all other from client request will be stripped. If it is expected behaviour, I think it should be documented somewhere.

You are right, but at the moment, we are not talking about 3xx redirects at Netlify CDN level (post you cited is about that). We are talking about redirects made at Origin Server level (status=200 in _redirects, not 3xx). For 3xx redirects netlify-cli and Edge Servers work the same way: all request params are appended to response Location if in the redirect to is not specifying any query param.

At the moment, there is no possible, to return 3xx redirect issued by Origin Server without empty query params if client request contains them. There are only two options: return all request query params or add any dummy query param within Origin response to obscure requests ones.

For me, this scenarion makes a lot of sense in case of redirects on the CDN level, but not necessarily when the redirection logic (as much as we want, including rewriting all parameters to the response) is handled by the Origin server.

If you disagree, I think this topic can be closed, but I won’t be very happy about it :wink:

We disregard the “preserved” params if the destination sends any query param in a response. So, it’s not about status_code being the only one that’s dropped, we’re dropping url too, but since the other server is sending the url param, you’re seeing that. To verify, you can try visiting:

https://wonderful-selkie-849613.netlify.app/redirect-to?url=https%3A%2F%2Fexample.com%2F%3Furl2%3Dexample2.com&status_code=303

Now you’ll see url2 as the query param on the final URL.

Regarding the guide talking about 3xx, I think you misunderstood/misread. There was one key line:

So we were always doing this for the 200 rewrite, which you’re using. Based on that guide, we just started doing it for 3xx as well.

The change, if made now could break the workflows of various websites that might be relying on this behaviour. The ideal way, I believe would be to add a configuration option. If that sounds okay to you, I can add that as a feature request. If you feel differently, let us know.

IMHO, there will be more sense for passthrough query param only from Netlify proxy to the origin. That is my understanding of “preserving params”. There is no option to check this behaviour before 301/302 update, but I think actual behaviour may be side-effect of this update.

If you think, you may add the feature request for optional disabling query params passthrough for 3xx responses returned by origin server (200 redirect rule). For some use cases it may be vital.

Netlify does attempt to preserve the query parameters that were passed. This is applicable to all 3xx redirects. For instance, if you have a redirect rule with a 301 or 302 HTTP status, Netlify will automatically pass on all query string parameters to the destination paths. However, you can also choose to define a redirect path based on a specific parameter or combination of parameters.

This is applicable to all 3xx redirects. For instance, if you have a redirect rule with a 301 or 302 HTTP status, Netlify will automatically pass on all query string parameters to the destination paths.

Yes, you are right, but we are talking about 200 redirect rule. Current behavior does not allow to ‘consume’ query string by origin server. In other words, it is not possible to return redirect Location without any query string.

I have to say I’ve just been dealing with this issue too, with a status=200 proxy and a function returning a Location header.

I’m porting a google lambda function over, and have just wasted a bunch of time trying to debug why the redirect behaviour broke.

In my opinion, if a function returns a Location header it should be passed through unchanged.

Maybe Netlify could add support for an extra response header, which indicates “No,really, trust me and accept my Location header verbatim” ?

I’m not sure if I understand your concern @wintrmute. Are you saying that your function is sending a location header and we’re not passing that correctly?

Netlify modifies the Location response.
If the incoming request has query parameters, and my function does not put query parameters on the Location header, then Netlify adds them. That is surprising behaviour, especially as:

  • the local netlify dev doesn’t do this
  • other cloud function service providers don’t do this

Can you confirm if we’re modifying the location header or simply preserving the query params on the redirected URL? Your previous comment made it seem as if we’re modifying the location header. Based on your last message it sounds like, the redirect that happens after you send a 301 with a location header has the query params. These are 2 different issues though they might seem similar.

The modification of location header sounds like a more severe issue than preserving query params (which is the current expected behaviour).