无url解码的Nginx pass_代理子目录

无url解码的Nginx pass_代理子目录,nginx,Nginx,我需要编写一个nginx location指令,将对子目录的请求代理到另一台服务器保存urlencoding和删除子目录前缀 下面是一个人工示例-请求如下: http://1.2.3.4/api/save/http%3A%2F%2Fexample.com 应作为 http://abcd.com/save/http%3A%2F%2Fexample.com 我试过几种不同的方法。这里有两个: 从 但是它会解码字符串,所以http://abcd.com获取/save/http://example

我需要编写一个nginx location指令,将对子目录的请求代理到另一台服务器保存urlencoding删除子目录前缀

下面是一个人工示例-请求如下:

http://1.2.3.4/api/save/http%3A%2F%2Fexample.com
应作为

http://abcd.com/save/http%3A%2F%2Fexample.com
我试过几种不同的方法。这里有两个:

  • 但是它会解码字符串,所以
    http://abcd.com
    获取
    /save/http://example.com

  • 但是它保留子目录,所以
    http://abcd.com
    获取
    /api/save/http%3A%2F%2Fexample.com

    需要的是中间的某个地方。谢谢大家!

    UPD:这里有一个在nginx中的bug跟踪器

    但是没有简单的方法来修复nginx的这种行为。nginx trac中有一些bug,您可以添加自己的。trac.nginx.org/nginx/…。所以,我认为最简单的方法就是拥有子域亚历克赛10号2月24日15时14分49分

    如果您想让nginx做一些定制的事情,可以使用​带有变量的proxy_pass(和$request_uri变量,该变量包含客户端发送的原始未经转换的请求uri)。在这种情况下,您将负责执行正确的URI转换。但请注意,这很容易导致安全问题,因此应小心操作

    接受挑战

        location /api/ {
            rewrite ^ $request_uri;
            rewrite ^/api/(.*) $1 break;
            return 400;
            proxy_pass http://127.0.0.1:82/$uri;
        }
    
    就这样,伙计们


    这是完整的证据

    nginx/1.2.1的配置文件:

    server {
        listen 81;
        #first, the solution
        location /api/ {
            rewrite ^ $request_uri;
            rewrite ^/api/(.*) $1 break;
            return 400; #if the second rewrite won't match
            proxy_pass http://127.0.0.1:82/$uri;
        }
        #next, a few control groups
        location /dec/ {
            proxy_pass http://127.0.0.1:82/;
        }
        location /mec/ {
            rewrite ^/mec(/.*) $1 break;
            proxy_pass http://127.0.0.1:82;
        }
        location /nod/ {
            proxy_pass http://127.0.0.1:82;
        }
    }
    
    server {
        listen 82;
        return 200 $request_uri\n;
    }
    
    以下是对每个位置运行查询的结果:

    % echo localhost:81/{api,dec,mec,nod}/save/http%3A%2F%2Fexample.com | xargs -n1 curl
    /save/http%3A%2F%2Fexample.com
    /save/http:/example.com
    /save/http:/example.com
    /nod/save/http%3A%2F%2Fexample.com
    %
    
    注意,有额外的
    返回400
    非常重要-否则,您可能会遇到安全问题(通过
    //api
    等进行文件访问),正如Maxim在您的trac记录单中简要提到的那样



    另外,如果您认为将重写引擎用作有限状态自动机非常酷,您可能还想查看我的项目,或者。

    只要我们讨论前缀匹配与
    ^ ~
    或不使用修饰符,您所要做的就相当容易了

    location /api/ {
      # if you don't want to pass /api/ add a trailing slash to the proxy_pass
      proxy_pass http://localhost:8080/;
    
      ...
    }
    
    所有内容都将在不解码的情况下传递,您不必传递
    $uri

    此外,在使用代理传递时,还应设置这些标头

    # pass headers and body along
    proxy_pass_request_headers on;
    proxy_pass_request_body on;
    
    # set some headers to make sure the reverse proxy is passing along everything necessary
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    

    你可以和lua一起试试。但首先,您不应该需要这个,根据http规范,这些URL是相同的,可以使用子域而不是subdirectory@AlexeyTen在
    http://abcd.com
    正在以不同的方式处理这些请求,我无法控制它。你知道那个http规范摘录的链接吗?我找不到itRFC 2616第3.2节。3@AlexeyTen它说,除了“保留”和“不安全”集合中的字符(参见RFC 2396[42])之外的其他字符等同于它们的“%”十六进制编码。我不知道RFC 2396中的
    [42]
    是什么,但是RFC中的第2.2节说那些字符是保留的-
    “;”/“|”?“|”:“|”@“|”&“|”=“|”+“|”$”,“
    真的。。谢谢你。真正的哇,当它真的像预期的那样工作的时候。考虑到与现有规则的相似性,神奇之处显然在于$request_uri捕获;重写^/api(/.*)$1中断;返回400;代用通行证;答案应该被接受。非常感谢您在事情突然开始奇怪地工作时给予的帮助!喜欢
    返回200$request\u uri\nlocalhost
    上游。
    location /api/ {
      # if you don't want to pass /api/ add a trailing slash to the proxy_pass
      proxy_pass http://localhost:8080/;
    
      ...
    }
    
    # pass headers and body along
    proxy_pass_request_headers on;
    proxy_pass_request_body on;
    
    # set some headers to make sure the reverse proxy is passing along everything necessary
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;