如何让 nginx 重定向到 url 编码的查询参数
How to get nginx to do a redirect to url-encoded query parameter
我需要根据示例通过查询参数对 url 进行代理调用:
我的 nginx 代理部署在:https://myproxy.net
如果重定向参数未 url 编码,我可以使用此块进行调用:
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass $arg_redirect;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}
错误拦截和@handle_redirects然后处理可能在新目的地弹出的其他 30X 代码。
这适用于请求:
GET
: https://myproxy.net/basepath?redirect=https://destination.com/somepath/uuid
我需要做什么才能使其适用于:
GET
: https://myproxy.net/basepath?redirect=https%3A%2F%2Fdestination.com%2Fsomepath%2Fuuid
此外,作为规范的一部分,它必须是纯 nginx,而不是其他模块,lua 等。
谢谢!
试一试,如果可行请告诉我
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
set_unescape_uri $decodedredirect $arg_redirect;
proxy_pass $decodedredirect;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}
实际上,proxy_pass
默认会进行归一化,但它只影响$uri
部分。因此,您只需要解码传递的字符串的开头即可使其正常工作:
location / {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
if ( $arg_redirect ~ (.+)%3A%2F%2F(.+) ){ # fix :// between scheme and destination
set $arg_redirect ://;
}
if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port
set $arg_redirect :;
}
if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
set $arg_redirect /;
}
proxy_pass $arg_redirect;
}
通过以上我成功访问了http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs
解决方案似乎很脏,使用默认模块的唯一替代方案是 map
(我认为更不干净)。我宁愿将 redirect
参数分成几个部分:方案(http 或 https)、目标、端口和 uri。这样你就可以在不重写的情况下构建完整地址:
proxy_pass $arg_scheme://$arg_dest:$arg_port/$arg_uri
好的,有一个非常奇怪和好奇的解决方案
server {
listen 80;
resolver x.x.x.x;
location /basepath {
if ($arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass http://127.0.0.1:80/basepath/$arg_redirect;
}
location ~ ^/basepath/(?<proto>\w+):/(?<redir>.+)$ {
proxy_pass $proto://$redir;
}
}
Nginx 不对 proxy_pass 中的变量路径进行编码并按原样发送。所以,我将 $arg_* 作为 proxy_pass uri 的一部分,向自己发送请求,nginx 将接收新的请求,该请求将被解码。
但是因为 Nginx 会清理路径并将 //
替换为 /
我在正则表达式中拆分了协议部分。
而且...我绝不会推荐使用此解决方案,但它确实有效:)
我需要根据示例通过查询参数对 url 进行代理调用:
我的 nginx 代理部署在:https://myproxy.net
如果重定向参数未 url 编码,我可以使用此块进行调用:
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass $arg_redirect;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}
错误拦截和@handle_redirects然后处理可能在新目的地弹出的其他 30X 代码。
这适用于请求:
GET
: https://myproxy.net/basepath?redirect=https://destination.com/somepath/uuid
我需要做什么才能使其适用于:
GET
: https://myproxy.net/basepath?redirect=https%3A%2F%2Fdestination.com%2Fsomepath%2Fuuid
此外,作为规范的一部分,它必须是纯 nginx,而不是其他模块,lua 等。 谢谢!
试一试,如果可行请告诉我
location /basepath {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
set_unescape_uri $decodedredirect $arg_redirect;
proxy_pass $decodedredirect;
proxy_intercept_errors on;
error_page 301 302 307 = @handle_redirects;
}
实际上,proxy_pass
默认会进行归一化,但它只影响$uri
部分。因此,您只需要解码传递的字符串的开头即可使其正常工作:
location / {
if ( $arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
if ( $arg_redirect ~ (.+)%3A%2F%2F(.+) ){ # fix :// between scheme and destination
set $arg_redirect ://;
}
if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port
set $arg_redirect :;
}
if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
set $arg_redirect /;
}
proxy_pass $arg_redirect;
}
通过以上我成功访问了http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs
解决方案似乎很脏,使用默认模块的唯一替代方案是 map
(我认为更不干净)。我宁愿将 redirect
参数分成几个部分:方案(http 或 https)、目标、端口和 uri。这样你就可以在不重写的情况下构建完整地址:
proxy_pass $arg_scheme://$arg_dest:$arg_port/$arg_uri
好的,有一个非常奇怪和好奇的解决方案
server {
listen 80;
resolver x.x.x.x;
location /basepath {
if ($arg_redirect = '') {
return 400 "Missing redirect directive in request";
}
proxy_pass http://127.0.0.1:80/basepath/$arg_redirect;
}
location ~ ^/basepath/(?<proto>\w+):/(?<redir>.+)$ {
proxy_pass $proto://$redir;
}
}
Nginx 不对 proxy_pass 中的变量路径进行编码并按原样发送。所以,我将 $arg_* 作为 proxy_pass uri 的一部分,向自己发送请求,nginx 将接收新的请求,该请求将被解码。
但是因为 Nginx 会清理路径并将 //
替换为 /
我在正则表达式中拆分了协议部分。
而且...我绝不会推荐使用此解决方案,但它确实有效:)