没有URL解码的Nginx pass_proxy子目录 [英] Nginx pass_proxy subdirectory without url decoding

查看:86
本文介绍了没有URL解码的Nginx pass_proxy子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to write an nginx location directive to proxy requests to subdirectory to another server preserving urlencoding and removing subdirectory prefix.

这是一个虚构的示例-这样的请求:

Here's an artificial example — request like this:

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

应通过

http://abcd.com/save/http%3A%2F%2Fexample.com

我尝试了几种不同的方法.这是其中的几个:

I tried several different ways. Here're couple of them:

  1. 来自此SO问题

location /api/ { rewrite ^/api(/.*) $1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; } 但是它会解码字符串,因此http://abcd.com获取/save/http://example.com

location /api/ { rewrite ^/api(/.*) $1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; } But it decodes the string, so http://abcd.com gets /save/http://example.com

  1. 来自另一个SO问题

location /api/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; }

location /api/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://abcd.com; }

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

But it keeps subdirectory, so http://abcd.com gets /api/save/http%3A%2F%2Fexample.com.

所需要的是中间的某个地方.谢谢!

What's needed is somewhere in the middle. Thank you!

UPD:这是nginx错误跟踪器中的门票

UPD: Here's a ticket in nginx bug tracker

推荐答案

但是没有简单的方法可以解决此nginx行为. Nginx Trac中有一些错误,您可以添加. trac.nginx.org/nginx/….因此,我认为最简单的方法是拥有子域. –阿列克谢(Alexey)2015年2月24日在14:49

But there is no easy way to fix this nginx behaviour. There are some bugs in nginx trac, you could add yours. trac.nginx.org/nginx/…. So, I think that the simplest way is to have subdomain. – Alexey Ten Feb 24 '15 at 14:49

https://trac.nginx.org/nginx/ticket/727

如果您想让Nginx做一些自定义的事情,可以使用带变量的proxy_pass(以及$ request_uri变量,该变量包含客户端发送的原始未转义的请求URI).在这种情况下,您有责任进行正确的URI转换.请注意,尽管这很容易引起安全问题,但应谨慎进行.

If you want nginx to do something custom, you can do so using ​proxy_pass with variables (and the $request_uri variable, which contains original unescaped request URI as sent by a client). In this case it will be your responsibility to do correct URI transformations. Note though that this can easily cause security issues and should be done with care.

接受挑战!

    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;
}

以下是针对每个位置运行查询的结果:

Here are the results of running the queries for each location:

% 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
%

请注意,拥有额外的return 400;非常重要 —否则,您将面临安全问题(通过//api等访问文件),就像Maxim在您的跟踪单中简要提到的那样.

Note that having that extra return 400; is quite important — otherwise, you risk having a security issue (file access through //api etc), as Maxim has briefly mentioned in your trac ticket.

P.S.如果您认为将重写引擎用作有限状态自动机非常酷,则可能还需要查看我的 http://mdoc. su/项目,或将其分叉github .

P.S. If you think using the rewrite engine as a finite-state automaton is super cool, you might also want check out my http://mdoc.su/ project, or fork it github.

这篇关于没有URL解码的Nginx pass_proxy子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆