Nginx location匹配规则
匹配顺序
官方文档解释如下:
A location can either be defined by a prefix string, or by a regular expression. Regular expressions are specified with the preceding “
~*
” modifier (for case-insensitive matching), or the “~
” modifier (for case-sensitive matching). To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used. If no match with a regular expression is found then the configuration of the prefix location remembered earlier is used.If the longest matching prefix location has the “
^~
” modifier then regular expressions are not checked.Also, using the “
=
” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a “/
” request happens frequently, defining “location = /
” will speed up the processing of these requests, as search terminates right after the first comparison. Such a location cannot obviously contain nested locations.
location 的定义分为两种:
- 前缀字符串(prefix string)
- 正则表达式(regular expression),正则表达式用 ~* 修饰符(用于不区分大小写的匹配)或 ~ 修饰符(用于区分大小写的匹配)。
匹配 location 的顺序为:
首先检查使用前缀字符串的 locations,选择并记住具有最长匹配前缀的 location。
如果最长匹配前缀的 location 带有
=
修饰符,并且 URI 相等匹配,则立刻停止匹配。如果最长匹配前缀的 location 带有
^~
修饰符,则也立刻停止匹配。^
表示非,~
表示正则,^~
就是表示不要继续匹配正则。除了^~
,=
也可阻止 nginx 继续匹配正则,区别在于^~
依然遵循最大前缀匹配规则,而=
是严格匹配。然后按照正则表达式在配置文件中的出现顺序检查正则表达式,正则表达式的搜索在第一次匹配时终止,并使用相应的 location。
如果没有找到与正则表达式匹配的 location,则使用先前记住的最长匹配前缀的 location。
Nginx配置测试示例
1 | server { |
等号匹配:
请求 https://test.liuzx.com.cn/aaa/ 返回内容 location = /aaa/ 。
匹配到最长前缀 location = /aaa/ ,带有 = 修饰符,并且 URI 相等,停止匹配。
非正则匹配:
请求 https://test.liuzx.com.cn/aaa/bbb/ 返回内容 location ^~ /aaa/bbb/ 。
匹配到最长前缀 location ^~ /aaa/bbb/ ,带有 ^~ 修饰符表示非正则匹配,停止匹配。
请求 https://test.liuzx.com.cn/aaa/bbb/ccc 返回内容 location ^~ /aaa/bbb/ 。
匹配到最长前缀 location ^~ /aaa/bbb/ ,带有 ^~ 修饰符表示非正则匹配,停止匹配。
正则匹配:
请求 https://test.liuzx.com.cn/aaa/bbb/ccc/ 返回内容 location ~ /aaa/bbb/ 。
为什么不是返回非正则匹配 location ^~ /aaa/bbb/ ,而是返回正则匹配 location ~ /aaa/bbb/ ?
首先找到最长匹配前缀 location /aaa/bbb/ccc/ ,并不是 location ^~ /aaa/bbb/ ,这是一个普通匹配,不带修饰符,记住当前 location;然后按顺序检查正则表达式,匹配到 location ~ /aaa/bbb/ 后终止,并且使用该 location 。
请求 https://test.liuzx.com.cn/ddd/eee/fff/ ,按照配置文件中的物理顺序正则匹配到 location ~ /ddd/eee/ ,直接返回内容 location ~ /ddd/eee/ 。
匹配到最长前缀 location /ddd/eee/ ,这是一个普通匹配,不带修饰符,记住当前 location;然后按顺序检查正则表达式,匹配到 location ~ /ddd/eee/ 后终止,并且使用该 location 。
请求 https://test.liuzx.com.cn/aAa/bbb/zzz ,返回内容 location ~* /aaa/bbb/ccc/ 。
匹配到不区分大小写的 location ~* /aaa/bbb/ 。
最长前缀匹配:
请求 https://test.liuzx.com.cn/ddd/ ,返回内容 location /ddd/ 。
匹配到最长前缀 location /ddd/ ,这是一个普通匹配,不带修饰符,记住当前 location;然后按顺序检查正则表达式,匹配不到 location,返回记住的 location 。
location格式
等号匹配(最高优先级)
1 | location = /aaa/ { |
非正则匹配
1 | location ^~ /aaa/bbb/ { |
正则匹配
区分大小写正则匹配
1 | location ~ /aaa/bbb/ { |
不区分大小写正则匹配
1 | location ~* /aaa/bbb/ { |
最长前缀匹配(最低优先级)
1 | location /aaa/bbb/ccc/ { |
参考
Nginx 官方文档:https://nginx.org/en/docs/http/ngx_http_core_module.html#location