我有一个基于 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;
}
}
希望这对某人有帮助。