遇到一个奇葩的问题, nginx访问Tomcat的时候, 我的请求地址中有中括号, 就会出现400的问题, 重点页面没有任何错误提示, 而且后台也没有任何错误日志.
问题还原
我的nginx配置如下
1 | location /files/ { |
Tomcat是使用Servlet的方式进行接收
1 | @WebServlet(name = "FileServlet", urlPatterns = "/file/*", loadOnStartup = 1) |
这样的情况下, 也就是, 如下的请求, 这是没有任何问题的
1 | http://host/files/folder1/folder2 |
如果这样子的话, 就有问题了
1 | http://host/files/folder1/folder2/01-[1]-file.file |
出现的错误页面
而这个页面没有任何的错误提示, 但是如果我将中括号改成大括号会有如下报错.
处理过程
搜搜搜
我google了半天, 找到几个, 大部分说在proxy_pass中删掉URI, 还有几个是说.
- request header过大
- proxy_set_header Host $host没有加
但是我这2个问题都没出现, 但是我的请求地址和header小得很, 以及我所有都加了Host这一条.
开Tomcat Debug
还是自己解决把, 因为没有错误日志, 连servlet都没收到请求, 我就开tomcat的Debug日志, 开debug很简单, 在/${tomcatRoot}/conf/logging.properties
简单加这一行就行了
1 | .level = FINE |
我添加在了如下的位置
1 | ... |
这样子启动tomcat, 会打印超多超多的日志, 然后我再次请求, 看到了这一条
1 | ..... |
但是我此时传入的这个url浏览器已经经过了urlEncode, 然后我尝试把后面的01-[1]-file.file
再次进行二次url, 变成01-%255B1%255D-file.file
(urlEncode2次), 然后看到请求是
1 | ... |
发现和浏览器的url地址是完全一致, 因此我觉得nginx没有对第二个进行解码, 而第一个nginx进行了解码后反代
找到问题
我看了下官网的proxy_pass的文档, Module ngx_http_proxy_module, 看到如下的内容, 就简单说下重要的部分
如果 proxy_pass 指向了一个指定的URL地址, 会对匹配的URL进行替换, 然后请求到后端Web服务.
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
如果 proxy_pass 没有携带任何URI, 那么地址以原始请求(即不做处理和匹配)
的形式请求后端Web服务, 或者在处理更改的URI时传递完整的规范化请求URI:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
当在proxy_pass中使用了变量时
location /name/ {
proxy_pass http://127.0.0.1$request_uri;
}即请求 http://host/name/aaa/bbb -> http://127.0.0.1/name/aaa/bbb
像这样的情况下, 会将URI原样的传递到服务器
解决
所以, 按照文档, 我的解决方案有以下2个(大部分说的是第一个)
1 | location /apps/files/ { |
或者是
1 | location /apps { |
对于第一种方案, 如果我访问/apps/image就要再配置一次, 因此, 第二个是满足了我的要求的, 但是, 如果是以下方式, 我暂时还没答案
这个就不会了…
1 | http://host/content/folder1/folder2/01[1].file |