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

前端 未结 4 1041
悲&欢浪女
悲&欢浪女 2020-12-01 14:11

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?<

相关标签:
4条回答
  • 2020-12-01 14:45

    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/;

    0 讨论(0)
  • 2020-12-01 14:47

    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.

    0 讨论(0)
  • 2020-12-01 14:51

    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 misses 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;
    }
    
    0 讨论(0)
  • 2020-12-01 15:03

    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

    0 讨论(0)
提交回复
热议问题