我在几个tomcats面前使用nginx作为负载balencer。在我的传入请求中,我编码了查询参数。但是当请求到达tomcat时,参数将被解码:
传入nginx的请求:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"
传入tomcat的请求:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"
我不希望我的请求参数被转换,因为在那种情况下我的tomcat会抛出405错误。
我的nginx配置如下:
upstream tracking {
server front-01.server.com:8080;
server front-02.server.com:8080;
server front-03.server.com:8080;
server front-04.server.com:8080;
}
server {
listen 80;
server_name tracking.server.com;
access_log /var/log/nginx/tracking-access.log;
error_log /var/log/nginx/tracking-error.log;
location / {
proxy_pass http://tracking/webapp;
}
}
在我当前的apache负载均衡器配置中,我有AllowEncodedSlashes指令保留了我的编码参数:
AllowEncodedSlashes NoDecode
我需要从apache转到nginx。
我的问题与这个问题完全相反:Avoid nginx escaping query parameters on proxy_pass
答案 0 :(得分:38)
我终于找到了解决方案:我需要通过$request_uri
parameter:
location / {
proxy_pass http://tracking/webapp$request_uri;
}
这样,在原始请求中编码的字符将不被解码,即将按原样传递给代理服务器。
答案 1 :(得分:13)
Jean's answer很好,但它不适用于sublocations。在这种情况下,更通用的答案是:
location /path/ {
if ($request_uri ~* "/path/(.*)") {
proxy_pass http://tracking/webapp/$1;
}
}
答案 2 :(得分:10)
如果需要以未处理的形式传输URI,则应使用指令proxy_pass 不带URI部分:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
所以在你的情况下它可能是这样的。不要担心它将被传递给上游服务器的请求URI
location / {
proxy_pass http://tracking;
}
希望它有所帮助。
答案 3 :(得分:5)
请注意,nginx文档中的URL解码,通常称为 $uri
"规范化" ,发生在后端IFF之前:
任何URI都在proxy_pass
内指定,即使只是尾随斜杠,
或者,URI在处理期间更改,例如通过rewrite
。
这两个条件都明确记录在http://nginx.org/r/proxy_pass(强调我的):
如果{<1}}指令 指定了 ,那么当请求传递给服务器时, normalized 请求与该位置匹配的URI将被指令
中指定的URI替换
如果指定{strong> 没有URI
时,会通过 传递URIproxy_pass
,请求URI将以 相同的形式传递到服务器处理原始请求时,客户 , 或 完整的 规范化 请求当 处理 更改的URI
解决方案取决于您是否需要更改前端和后端之间的URL。
如果不需要更改URI:
proxy_pass
否则,如果您确实需要在后端交换或映射前端的# map `/foo` to `/foo`:
location /foo {
proxy_pass http://localhost:8080; # no URI -- not even just a slash
}
与/api
,那么您可以从$request_uri
获取原始URI变量,并使用类似于DFA的/app
变量rewrite
指令(BTW,如果您想要更多$uri
DFA操作,请查看mdoc.su)。请注意,如果有人试图绕过您的第二个重写规则,则需要rewrite
部分,因为它不会匹配return 400
之类的内容。
//api/
如果您只是想为后端添加前缀,那么您可以立即使用# map `/api` to `/app`:
location /foo {
rewrite ^ $request_uri; # get original URI
rewrite ^/api(/.*) /app$1 break; # drop /api, put /app
return 400; # if the second rewrite won't match
proxy_pass http://localhost:8080$uri;
}
变量:
$request_uri
您可能还想查看a related answer,其中显示了与上述类似的代码的一些测试运行。
答案 4 :(得分:-2)
在某些情况下,问题不在nginx端 - 您必须将Tomcat连接器上的uri编码设置为UTF-8。