今天和同事讨论一个有关 nginx 中的location
配置问题,就想查一下它的匹配规则。结果 Google 出的文章基本都是同一篇,而且各种莫名其妙的示例看得自己更云里雾里,索性上官网查文档,现对它的用法做个梳理。
语法
1 2 |
location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } |
这是location
的使用方法,这里暂不考虑@
的用法。
分类
匹配规则其实可以分为两类:
prefix string
:即前缀字符串匹配,包括= uri
、^~ uri
和uri
三种形式。regex
:即正则匹配,包括~ uri
(大小写敏感)和~* uri
(大小写不敏感)两种形式。
匹配过程
nginx 对 location 的匹配流程为:
- 首先遍历 location 规则中所有的 prefix string 类型,如果有
=
规则并且=
后的 uri 和请求的 uri 完全匹配,那么直接命中该条规则,然后立刻终止匹配;若无满足上述条件,则进行下一步。 - 上一步中没有匹配的
=
规则,nginx 会持续遍历完成所有的 prefix string 类型规则。遍历完成后,如果有单个匹配的^~
规则,则直接命中该规则,并终止匹配;如果有多条匹配的^~
规则,则命中多条中的最长一条匹配规则,并终止匹配。若无满足上述条件,则进行下一步。 - 在上一步的遍历结果中,找到最长匹配(此时为
uri
的形式),并且记录它,进行下一步(注意,此步并不终止匹配)。 - 遍历所有的
regex
类型匹配。按照正则匹配规则的出现顺序进行比对,找到的第一条正则匹配作为命中的规则,然后终止返回。如果遍历结束没有找到匹配的正则规则,则取出上一步记录的uri
形式的最长匹配,命中该规则,终止返回。
以上就是location
匹配的规则。
特殊处理
有一种特殊情况需要注意:
- 如果有一条 prefix string 类型的 location 规则,它的 uri 以斜杠
/
结尾。 - 该条规则为
proxy_pass
,fastcgi_pass
,uwsgi_pass
,scgi_pass
,memcached_pass
类型之一。
同时满足上述连个条件,那么一个尾部不带/
的请求 uri 会被永久重定向(301)
到由该 uri 尾部加上一个/
的新 uri 去,并命中该条规则。比如如果设置了下面这条规则:
1 2 3 |
location /user/ { proxy_pass: http://user.example.com; } |
那么请求/user
这个 uri 会被永久重定向到/user/
这个 uri 并命中上面这条规则。如果确实想针对/user
这个 uri 做一条规则匹配而不重定向,那么可以用精确匹配如下设置:
1 2 3 |
location = /user { proxy_pass: http://user.example.com; } |
讨论
其实今天同事最初问的是 location 中的非匹配规则怎么写,说没有找到。但是感觉应该不需要该功能,因为如果存在非匹配,那么大多数情况应该需要在该条规则中继续嵌套各种匹配规则;而且下一条规则只可能有一种,就是匹配该 uri 的规则,变得没有意义。
以上就是总结的 nginx 中location
匹配规则,有空会再加上@
的应用场景。
注:转载注明出处并联系作者,本文链接:https://nodefe.com/nginx-configuration-location/
你这总结的不对啊,第二条中『遍历完成后,如果有单个匹配的^~规则,则直接命中该规则,并终止匹配』,应该是匹配最长的前缀字符串匹配,如果这个最长的前缀字符串匹配是一个^~规则,则终止匹配(即不再匹配正则)
你好,抱歉没有看出你说的和我写的有什么不同。。 “应该是匹配最长的前缀字符串匹配,如果这个最长的前缀字符串匹配是一个^~规则,则终止匹配(即不再匹配正则)。” 我写的是对于^~规则,如果有单条,直接命中并终止,如果有多条,则命中最长的那条并终止匹配。如果命中非^~规则的前缀匹配,则仍然进行正则匹配,即走入下一步。
简洁明了