如何让nginx重定向到url编码的查询参数

如何让nginx重定向到url编码的查询参数,nginx,nginx-reverse-proxy,nginx-location,Nginx,Nginx Reverse Proxy,Nginx Location,我需要通过查询参数对url进行代理调用,如示例所示: 我的nginx代理部署在:https://myproxy.net 如果重定向参数不是url编码的,我可以使用以下块进行调用: location /basepath { if ( $arg_redirect = '') { return 400 "Missing redirect directive in request"; } proxy_pass

我需要通过查询参数对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_重定向,然后处理可能在新目的地弹出的其他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;
    }

试着这样,让我知道它是否有效

  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\u 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 $1://$2;
    }
    if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port
      set $arg_redirect $1:$2;
    }
    if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
      set $arg_redirect $1/$2;
    }
    proxy_pass $arg_redirect;
  }
通过以上内容,我成功访问了
http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs

这个解决方案看起来很脏,使用默认模块的唯一选择是
map
(我认为更不干净)。我宁愿将
redirect
参数分成几个部分:scheme(http或https)、destination、port和uri。这样,您就可以构建完整地址,而无需重写:

proxy_pass $arg_scheme://$arg_dest:$arg_port/$arg_uri

实际上,默认情况下,
proxy\u 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 $1://$2;
    }
    if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port
      set $arg_redirect $1:$2;
    }
    if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass
      set $arg_redirect $1/$2;
    }
    proxy_pass $arg_redirect;
  }
通过以上内容,我成功访问了
http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs

这个解决方案看起来很脏,使用默认模块的唯一选择是
map
(我认为更不干净)。我宁愿将
redirect
参数分成几个部分:scheme(http或https)、destination、port和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;
  }
}
服务器{
听80;
分解器x.x.x.x;
位置/基本路径{
如果($arg_redirect=''){
返回400“请求中缺少重定向指令”;
}
代理通行证http://127.0.0.1:80/basepath/$arg_重定向;
}
位置^/basepath/(?\w+):/(?。+)${
代理通行证$proto://$redir;
}
}
Nginx不使用proxy_pass中的变量对路径进行编码并按原样发送。所以,我将$arg作为代理传递uri的一部分,将请求发送给self,nginx将接收新的请求,该请求将被解码

但因为Nginx将清理路径并将
/
替换为
/
我在regexp中拆分了协议部分


而且。。。我永远不会推荐使用这个解决方案,但它是有效的:)

好的,有一个非常奇怪的解决方案

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;
  }
}
服务器{
听80;
分解器x.x.x.x;
位置/基本路径{
如果($arg_redirect=''){
返回400“请求中缺少重定向指令”;
}
代理通行证http://127.0.0.1:80/basepath/$arg_重定向;
}
位置^/basepath/(?\w+):/(?。+)${
代理通行证$proto://$redir;
}
}
Nginx不使用proxy_pass中的变量对路径进行编码并按原样发送。所以,我将$arg作为代理传递uri的一部分,将请求发送给self,nginx将接收新的请求,该请求将被解码

但因为Nginx将清理路径并将
/
替换为
/
我在regexp中拆分了协议部分


而且。。。我永远不会推荐使用这个解决方案,但它是有效的:)

谢谢你的想法,但是
set\u???
指令是我的道歉的一部分我错过了“纯nginx,不是附加模块”谢谢你的想法,但是
set\u???
指令是我的道歉我错过了“纯nginx,不是附加模块”的一部分感谢您提供的替换示例。将url拆分为段的想法很简单,我真的应该想到,这绝对是迄今为止最干净的解决方案!感谢您提供的替换示例。将url拆分为段的想法很简单,我真的应该想到,这绝对是迄今为止最干净的解决方案!