如何在 nginx 内部遵循 HTTP 重定向?

如何在 nginx 内部遵循 HTTP 重定向?

我有一个基于 nginx 的 HTTP 代理,我想处理其中的所有 HTTP 重定向,以便客户端只获得重定向链中的最后一个响应。

基本代码如下:

location /proxy {
    rewrite ^/proxy/([^/]+) $1 break;

    proxy_pass http://$uri/;
}

我尝试遵循 1 级重定向如下:

error_page 301 302 307 =200 @redir;

...并具有此命名位置:

location @redir {
    proxy_pass $proxy_location;
}

只是没有 $proxy_location 变量,我找不到创建它的方法。它应该包含Location:从上游收到的标头的值。

有什么想法吗?

答案1

我相信你想要变量$上游_http_位置

以 $proxy* 开头的变量控制从 nginx 到上游的内容。$upstream* 系列变量包含有关 nginx 本身收到的响应的信息。您可以使用 $upstream_http_headername 获取从上游服务器收到的任何任意 HTTP 标头。

请注意,在收到上游服务器的响应之前,这些 $upstream 变量只能为空,因此它们的使用存在一些限制。

答案2

以下是对我有用的完整示例:

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_redirect;
    }

    location @handle_redirect {
        set $saved_redirect_location '$upstream_http_location';
        proxy_pass $saved_redirect_location;
    }
}

答案3

我在尝试代理来自以下来源的图像时遇到了类似的问题https://picsum.photos网站。当请求特定图片时,它们会返回 302 重定向到 HMAC 签名的 URL。

我的解决方案基于弗拉德的回答但是我添加了一些额外功能(标记为[1][2])以使其适合我:

server {
    listen 80;
    server_name dog.localhost.direct;
    location / { 
        # [1] pass the server name
        proxy_ssl_server_name on;
        proxy_intercept_errors on;
        error_page 301 302 307 = @handle_redirect;
        proxy_pass https://picsum.photos/id/237/536/354;
    }
    location @handle_redirect {
        set $saved_redirect_location '$upstream_http_location';
        # [2] specify a resolver
        resolver 8.8.8.8;
        proxy_pass $saved_redirect_location;
    }
}

希望这对某人有帮助。

相关内容