Intercepting backend 301/302 redirects (proxy_pass) and rewriting to another location block possible? Intercepting backend 301/302 redirects (proxy_pass) and rewriting to another location block possible? nginx nginx

Intercepting backend 301/302 redirects (proxy_pass) and rewriting to another location block possible?


You could use proxy_redirect directive:

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

Nginx will still return 301/302 to the client but proxy_redirect will modify Location header and the client should make a new request to the URL given in the Location header.

Something like this should make the subsequent request back to nginx:

proxy_redirect http://upstream:port/ http://$http_host/;


I succeeded in solving a more generic case when a redirect location can be any external URL.

server {    ...    location / {        proxy_pass http://backend;        # You may need to uncomment the following line if your redirects are relative, e.g. /foo/bar        #proxy_redirect / /;        proxy_intercept_errors on;        error_page 301 302 307 = @handle_redirects;    }    location @handle_redirects {        set $saved_redirect_location '$upstream_http_location';        proxy_pass $saved_redirect_location;    }}

Alternative approach, which is closer to what you describe, is covered in ServerFault answer to this question: https://serverfault.com/questions/641070/nginx-302-redirect-resolve-internally


If you need to follow multiple redirects, modify Vlad's solution as follows:

1) Add

recursive_error_pages on;

to location /.

2) Add

  proxy_intercept_errors on;  error_page 301 302 307 = @handle_redirect;

to the location @handle_redirects section.