nginx的路径变化
经常搞不清楚nginx的路径变化,特别是在proxy_pass的时候. 看下官方文档了解一下.
http://nginx.org/en/docs/http/ngx_http_core_module.html#location和 http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
先看一下路径的匹配规则
官方资料见 http://nginx.org/en/docs/http/ngx_http_core_module.html#location
location语法是这样的 location [ = | ~ | ~* | ^~ ] uri { ... }
, []里面的东西代表可有可无. 举一个例子
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
nginx在匹配路径之前, 会首先把uri中%XX这样格式的内容先解码, 然后把. ..转成绝对路径, 以及把多个//合并成一个/
在说明匹配规则前, 还是先解释一下上面这个语法什么意思. ~ ~*这两个代表uri是一个正则表达式, ~是大小写敏感, ~*是大小写不敏感. ^~可不是正则的意思,后面会有解释. 其它情况下, uri代表一个路径前缀.
匹配路径按以下规则进行:
-
先序遍历所有路径前缀, 把匹配的规则中最长的那个记录下来. 然后按顺序遍历所有正则, 第一个正则匹配成功之后就停下来. 如果没有正则可以成功匹配, 选用最长长度的前缀路径.
-
如果最长的前缀路径有 ^~ 修饰符, 直接选用这个, 1步骤里面的正则匹配就不用了.
-
在第一步遍历路径前缀时, 如果前缀路径有 = 修饰符, 则停止继续寻找,直接使用这个.
-
uri前面加一个@, 叫做 named location, 普通的请求不管他, 只用在一些内部的跳转上, 比如下面这样
location / { error_page 404 = @fallback; } location @fallback { proxy_pass http://backend; }
-
如果一个前缀路径最后以/结尾, 而且请求被proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, or memcached_pass中的一个处理, 这个情况比较特殊: 请求如果不以/结尾, 会返回一个301的重定向响应, 再最后加上/. 如果不想这样, 就要用 = 修饰符做精确匹配, 像下面这样
location /user/ { proxy_pass http://user.example.com; } location = /user { proxy_pass http://login.example.com; }
proxy_pass中的路径变换
我们用nginx curl python -m SimepleHTTPServer来做测试
-
如果proxy_pass含有URI,那么把标准化之后的Url中匹配location的那部分换成proxy_pass指令中的URI.
server { listen 8080; server_name proxy-pass-test-1.localhost; location /name/ { proxy_pass http://127.0.0.1:8000/remote/; } } curl proxy-pass-test-1.localhost:8080/name/abcd/xyz 127.0.0.1 - - [12/Jun/2017 14:16:32] "GET /remote/abcd/xyz HTTP/1.0" 404 -
-
如果proxy_pass没有URI, 那么完整的URI全部传递过去.
server { listen 8080; server_name proxy-pass-test-2.localhost; location /name/ { proxy_pass http://127.0.0.1:8000; } } curl proxy-pass-test-2.localhost:8080/name/abcd/xyz 127.0.0.1 - - [12/Jun/2017 14:23:18] "GET /name/abcd/xyz HTTP/1.0" 404 -
有些情况下, 无法判断被替换的部分, 比如:
-
location是正则匹配的, 或者是使用的named location
这种情况下, proxy_path不能使用URI
-
URI在内部被rewrite改变了, proxy_pass中的URI被忽略,完整的改变后的URI被传递.
server { listen 8080; server_name proxy-pass-test-3.localhost; location /name/ { rewrite /name/([^/]+) /users?name=$1 break; proxy_pass http://127.0.0.1:8000; } } server { listen 8080; server_name proxy-pass-test-4.localhost; location /name/ { rewrite /name/([^/]+) /users?name=$1 break; proxy_pass http://127.0.0.1:8000/remote/; } } curl -i proxy-pass-test-3.localhost:8080/name/childe 127.0.0.1 - - [12/Jun/2017 14:36:29] "GET /users?name=childe HTTP/1.0" 404 - curl -i proxy-pass-test-4.localhost:8080/name/childe 127.0.0.1 - - [12/Jun/2017 14:36:35] "GET /users?name=childe HTTP/1.0" 404 -
-
proxy_pass中使用变量
server { listen 8080; server_name proxy-pass-test-5.localhost; location /name/ { proxy_pass http://127.0.0.1:8080/$request_uri; } } curl -i proxy-pass-test-5.localhost:8080/name/abcd/xyz 127.0.0.1 - - [12/Jun/2017 14:41:02] "GET /name/abcd/xyz HTTP/1.0" 404 -