Nginx代理拦截重定向并将自定义重定向传递给客户端

Nginx代理拦截重定向并将自定义重定向传递给客户端,nginx,redirect,proxy,Nginx,Redirect,Proxy,我有一个web应用程序,它希望在不启用CORS的情况下从第三方站点访问文件。请求可以发送到具有任意参数的任意域。我正在向我的域发送一个包含编码为GET参数的目标的请求,即 GET https://www.example.com/proxy/?url=http%3A%2F%2Fnginx.org%2Fen%2Fdocs%2Fhttp%2Fngx_http_proxy_module.html 那么在Nginx我会的 location /proxy/ { resolver 8.8.8.8;

我有一个web应用程序,它希望在不启用CORS的情况下从第三方站点访问文件。请求可以发送到具有任意参数的任意域。我正在向我的域发送一个包含编码为GET参数的目标的请求,即

GET https://www.example.com/proxy/?url=http%3A%2F%2Fnginx.org%2Fen%2Fdocs%2Fhttp%2Fngx_http_proxy_module.html
那么在Nginx我会的

location /proxy/ {
    resolver 8.8.8.8;
    set_unescape_uri $dst $arg_url;
    proxy_pass $dst;
}
这适用于单个文件,但目标服务器有时会返回一个Location头,我想截取并修改它,以便客户端重试

基本上,我希望转义$sent\u http\u位置,将其附加到并将其传递回浏览器以重试

我试过了

set_escape_uri $tmp $sent_http_location;
proxy_redirect $sent_http_header /pass/?v=$tmp;
但这不起作用。我还尝试保存位置头,然后用

proxy_hide_header
用我自己的来代替它

proxy_set_header
但是忽略会导致我丢失保存它的变量


如何配置Nginx来完成重定向处理,以便在代理站点重定向时将返回给用户的编码URL传递给用户?

您不成功的方法存在几个问题:

proxy_set_header设置发送到上游服务器而不是客户端的头。因此,即使$sent\u http\u位置不是空的,您的配置也不可能按您所希望的那样工作

$sent_http_变量指向与将发送到客户端的响应头完全相同的内存区域。因此,当proxy_hide_头生效时,指定的头将与相应的$sent_http_头的值一起从内存中删除

set_escape_uri在请求处理的早期阶段工作,即在调用proxy_pass和从上游服务器返回位置头之前。因此,它将始终处理当时的空变量$sent\u http\u location,结果也将始终是空变量

最后一个问题是最严重的。让set_escape_uri在代理传递后工作的唯一方法是强制Nginx离开当前位置并重新开始处理。这可以通过错误页面技巧完成:

注意使用$upstream\u http\u location而不是$sent\u http\u location。当Nginx离开位置的上下文时,它假设请求将被代理到另一个上游,或者以其他方式处理,因此它清除从上一个代理传递接收到的头,为新的响应头腾出空间

与$sent_http_uuvairables(表示将发送到客户端的响应头)不同,$upstream_http_u变量表示从上游接收的响应头。因此,只有当请求被代理到另一个上游服务器时,才会用新值替换它们。因此,一旦设置,这些变量可以随时使用,它们将不会被清除

location /proxy/ {
    resolver 8.8.8.8;
    set_unescape_uri $dst $arg_url;
    proxy_pass $dst;

    proxy_intercept_errors on;
    error_page 301 = @rewrite_301;
}

location @rewrite_301 {
    set_escape_uri $location $upstream_http_location;
    return 301 /pass/?v=$location;
}