Nginx 的 location 用于匹配 URI 不同路径的请求,实现对请求的细分处理。例如当客户端请求 https://www.nginx-test.com/index.html 时,Nginx 使用本地的静态文件响应,而当客户端请求相同地址的 https://www.nginx-test.com/api 时,Nginx 将请求转发到后端服务器。
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location
=
表示精确匹配。只有请求的url路径与后面的字符串完全相等时,才会命中。使用 =
精确匹配可以加快查找的顺序。^~
表示如果该符号后面的字符是最佳匹配(前缀匹配),采用该规则,不再进行后续的查找。~
表示该规则是使用正则定义的,区分大小写。~*
表示该规则是使用正则定义的,不区分大小写。!~
表示正则区分大小写不匹配。!~*
表示正则不区分大小写不匹配。当收到一个url请求时:
=
修饰符的location,结束查找,使用它的配置。或者如果通过最长匹配原则匹配到的前缀字符定义的 location 并且是以^~
作为修饰符的,结束查找,使用它的配置。3.如果没有匹配的正则表达式的 location,则使用前面记录的最长匹配前缀字符的 location。
匹配过程图示
image.png
接下来我们以一个例子来说明具体的匹配过程。配置文件:
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
/
精准匹配A,不再往下查找。/index.html
匹配 B。首先查找匹配的前缀字符,找到最长匹配是配置 B,接着又按照顺序查找匹配的正则。结果没有找到,因此使用先前标记的最长匹配,即配置 B。/documents/document.html
匹配 C。首先找到最长匹配 C,由于后面没有匹配的正则,所以使用最长匹配 C。/images/1.gif
匹配 D。首先进行前缀字符的查找,找到最长匹配 D。但是,特殊的是它使用了 ^~
修饰符,不再进行接下来的正则的匹配查找,因此使用 D。这里,如果没有前面的修饰符,其实最终的通过正则匹配的是 E。/documents/1.jpg
匹配 E。首先进行前缀字符的查找,找到最长匹配项 C,继续进行正则查找,找到匹配项 E。@
用来定义一个命名 location。主要用于内部重定向,不能用来处理正常的请求。其用法如下:
location / {
try_files $uri $uri/ @redirectUri
}
location @redirectUri {
# ...do something
}
上例中,当尝试访问 url 找不到对应的文件就重定向到我们自定义的命名 location(此处为 @redirectUri)。命名 location 中不能再嵌套其它的命名 location。
location /test {
...
}
location /test/ {
...
}
ip地址/test
时, Nginx 先找是否有 test 目录,如果有则找 test 目录下的 index.html;如果没有 test 目录, nginx 则会找是否有 test 文件。ip地址/test
时, Nginx 先找是否有 test 目录,如果有则找 test 目录下的 index.html,如果没有它也不会去找是否存在 test 文件。这里结合 location 和 proxy 对反斜线做进一步说明。proxy_pass 用于配置代理服务器。
语法如下:
Syntax: proxy_pass URL;
Default: —
Context: location, if in location, limit_except
URL 参数原则:
接下来让我们来看看两种常见的 URL 用法:
proxy_pass http://192.168.100.33:8081
proxy_pass http://192.168.100.33:8081/
这两种用法的区别就是带 / 和不带 / ,在配置代理时它们的区别可大了:
不带 / 的用法:
location /bbs/{
proxy_pass http://127.0.0.1:8080;
}
分析:
带 / 的用法:
location /bbs/{
proxy_pass http://127.0.0.1:8080/;
}
分析: