分类: 技术

Nginx 配置 location 匹配规则总结

今天和同事讨论一个有关 nginx 中的location配置问题,就想查一下它的匹配规则。结果 Google 出的文章基本都是同一篇,而且各种莫名其妙的示例看得自己更云里雾里,索性上官网查文档,现对它的用法做个梳理。

语法

这是location的使用方法,这里暂不考虑@的用法。

分类

匹配规则其实可以分为两类:

  1. prefix string:即前缀字符串匹配,包括= uri^~ uriuri三种形式。
  2. regex:即正则匹配,包括~ uri(大小写敏感)和~* uri(大小写不敏感)两种形式。

匹配过程

nginx 对 location 的匹配流程为:

  1. 首先遍历 location 规则中所有的 prefix string 类型,如果有=规则并且=后的 uri 和请求的 uri 完全匹配,那么直接命中该条规则,然后立刻终止匹配;若无满足上述条件,则进行下一步。
  2. 上一步中没有匹配的=规则,nginx 会持续遍历完成所有的 prefix string 类型规则。遍历完成后,如果有单个匹配的^~规则,则直接命中该规则,并终止匹配;如果有多条匹配的^~规则,则命中多条中的最长一条匹配规则,并终止匹配。若无满足上述条件,则进行下一步。
  3. 在上一步的遍历结果中,找到最长匹配(此时为uri的形式),并且记录它,进行下一步(注意,此步并不终止匹配)。
  4. 遍历所有的regex类型匹配。按照正则匹配规则的出现顺序进行比对,找到的第一条正则匹配作为命中的规则,然后终止返回。如果遍历结束没有找到匹配的正则规则,则取出上一步记录的uri形式的最长匹配,命中该规则,终止返回。

以上就是location匹配的规则。

特殊处理

有一种特殊情况需要注意:

  1. 如果有一条 prefix string 类型的 location 规则,它的 uri 以斜杠/结尾。
  2. 该条规则为proxy_passfastcgi_passuwsgi_passscgi_passmemcached_pass类型之一。

同时满足上述连个条件,那么一个尾部不带/的请求 uri 会被永久重定向(301)到由该 uri 尾部加上一个/的新 uri 去,并命中该条规则。比如如果设置了下面这条规则:

那么请求/user这个 uri 会被永久重定向到/user/这个 uri 并命中上面这条规则。如果确实想针对/user这个 uri 做一条规则匹配而不重定向,那么可以用精确匹配如下设置:

讨论

其实今天同事最初问的是 location 中的非匹配规则怎么写,说没有找到。但是感觉应该不需要该功能,因为如果存在非匹配,那么大多数情况应该需要在该条规则中继续嵌套各种匹配规则;而且下一条规则只可能有一种,就是匹配该 uri 的规则,变得没有意义。

以上就是总结的 nginx 中location匹配规则,有空会再加上@的应用场景。

注:转载注明出处并联系作者,本文链接:https://nodefe.com/nginx-configuration-location/

发表评论

评论

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

  1. 你这总结的不对啊,第二条中『遍历完成后,如果有单个匹配的^~规则,则直接命中该规则,并终止匹配』,应该是匹配最长的前缀字符串匹配,如果这个最长的前缀字符串匹配是一个^~规则,则终止匹配(即不再匹配正则)

    • 你好,抱歉没有看出你说的和我写的有什么不同。。 “应该是匹配最长的前缀字符串匹配,如果这个最长的前缀字符串匹配是一个^~规则,则终止匹配(即不再匹配正则)。” 我写的是对于^~规则,如果有单条,直接命中并终止,如果有多条,则命中最长的那条并终止匹配。如果命中非^~规则的前缀匹配,则仍然进行正则匹配,即走入下一步。

Webmentions

  • nginx 配置一例 – 张三太爷 07/26/2016

    简洁明了