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

We have a couple of backends sitting behind our nginx front ends.

Is it possible to intercept 301 / 302 redirects sent by these backends and have nginx handle them?

We were thinging something alone the lines of:

error_page 302 = @target;

But I doubt 301/302 redirects can be handled the same as 404's etc etc... I mean, error_page probably doesnt apply to 200, etc error codes?

So to summarize:

Our backends send back 301/302s once in a while. We would like to have nginx intercept these, and rewrite them to another location block, where we could do any number of other things with them.

Possible?

Thanks!

Answers


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.


More on proxy_redirect, for relative locations

Case
location /api/ {
  proxy_pass http://${API_HOST}:${API_PORT}/;
}
  • the backend redirects to a relative location, which miss the /api/ prefix
  • the browser follows the redirection and hits a wall of incomprehension
Solution
location /api/ {
  proxy_pass http://${API_HOST}:${API_PORT}/;
  proxy_redirect ~^/(.*) http://$http_host/api/$1;
}

Need Your Help

IntelliJ cannot find any declarations

java intellij-idea intellij-idea-2016

I completely uninstalled IntelliJ and have now reinstalled and imported my project. I imported using gradle and can see all of the files in my project present. However, when I open a file I can't f...

How to install libusb in Ubuntu

ubuntu libusb

I have a C program that have #include part in the header.