Skip to content

Latest commit

 

History

History
165 lines (89 loc) · 6.79 KB

location-detail.md

File metadata and controls

165 lines (89 loc) · 6.79 KB

location 详解

匹配顺序

  • location 的匹配顺序其实是先匹配普通,再匹配正则

  • 正则匹配会覆盖普通匹配(实际的规则,比这复杂)

执行顺序

  • 普通 location的匹配规则是“最大前缀”,普通 location与 location 编辑顺序无关。

  • 正则 location 的匹配规则是顺序匹配,且只要匹配到第一个就停止后面的匹配

  • 两种情况下,不需要继续匹配正则 location

    • 当普通 location 前面指定了^~ ,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配

    • 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。

  • 正则 location 匹配让步普通 location 的严格精确匹配结果,但覆盖普通 location 的最大前缀匹配结果

官方文档

  • 语法

    location
    syntax: location [=|~|~*|^~|@] /uri/ { … }
    default: no
    context: server
  • 正则location (location using regular expressions)

    • ~~* 前缀表示正则location

    • ~ 区分大小写

    • ~* 不区分大小写

  • 普通location (location using literal strings)

    • 无任何前缀的都属于普通 location

    • 其他前缀(包括:=^~@)也属于普通匹配

  • 对于特定的HTTP请求(a particular query),nginx应该匹配哪个location块的指令

    原文:To determine which location directive matches a particular query, the literal strings are checked first. 先普通location再正则location

  • 普通location普通location 是如何匹配的?

    • 匹配规则1:先匹配普通location,再匹配正则location

    • 匹配规则2:最大前缀匹配

    • 匹配规则3:匹配URI的前缀部分(match the beginning portion of the query)

    • 匹配规则4:最具体的匹配将被使用(the most specific match will be used),因为 location 不是严格匹配,而是前缀匹配,就会产生一个HTTP 请求,可以前缀匹配到多个普通location

    • 案例

      • 列如:location /prefix/mid/ {} location /prefix/ {}

      • 于HTTP 请求/prefix/mid/t.html,前缀匹配的话两个location都满足,该匹配哪个?

      • 匹配原则:最具体匹配原则the most specific match

      • 最后的匹配是:location /prefix/mid/ {}

  • 正则location正则location 是如何匹配的?

    • 匹配规则是:按照 正则location 在配置文件中的物理顺序(编辑顺序)匹配

    • 注意1:location 并不是一定跟顺序无关,只是普通 location与顺序无关,正则 location还是与顺序有关的

  • 正则location普通location最大匹配如何匹配?

    • 正则:只要匹配到一条正则location ,就不再考虑后面匹配

    • 普通:选择出“普通location”的最大前缀匹配结果后,还需要继续搜索正则location

  • (普通)最大前缀匹配结果与继续搜索的正则location匹配结果的决策关系

    • 原文:If no regular expression matches are found, the result from the literal string search is used. 如果找不到正则表达式匹配,则使用文字字符串搜索的结果

    • 匹配一:如果继续搜索的正则location也有匹配上的,那么正则location覆盖普通location的最大前缀匹配

    • 因为有这个覆盖关系,所以造成有些同学以为正则location 先于普通location 执行的错误理解

    • 但是如果“正则location ”没有能匹配上,那么就用“普通location ”的最大前缀匹配结果

  • 一般匹配原则

    • 匹配完了普通location指令,还需要继续匹配正则location

    • 也可以告诉Nginx:匹配到了普通location后,不再需要继续匹配正则location了,

      1.要做到这一点只要在普通location前面加上^~符号
      2.^ 表示~ 表示正则,字符意思是:不要继续匹配正则

    • ^~= 区别

      • 共同点:都能阻止继续搜索正则location

      • 不同点:

        1.^~依然遵守最大前缀匹配规则 2.=不是最大前缀,而是必须是严格匹配(exact match )

location / {} location = / {}的区别

  • location / {}

    • 遵守的是:普通location 的最大前缀匹配

    • 由于任何URI都必然以根开头,所以对于一个URI,如果有更具体(specific)的匹配,那自然是选这个更具体的匹配了,如果没有,/一定能为这个URI垫背(至少能匹配到/),可以说:location / {}有点像默认配置,其他更具体(specific)的配置能覆盖(overwrite)这个默认配置(这也是为什么总能看到location / {}这个配置的一个很重要的原因)

  • location = / {}

    • 遵守的是:严格精确匹配exact match

    • 只能匹配http://host:port/请求,同时会禁止继续搜索正则location

    • 因此如果我们只想对GET / 请求配置作用指令,那么我们可以选location = / {} 这样能减少正则location 的搜索,因此效率比location / {} 高

      注:前提是我们的目的仅仅只想对“GET / ”起作用

精确匹配

  • 精确匹配exact match ,即使普通location没有带=^~前缀,也一样会终止后面的匹配

  • 原文:On exact match with literal location without “=” or “^~” prefixes search is also immediately terminated

  • 最大前缀匹配恰好就是一个严格精确(exact match )匹配,照样会停止后面的搜索

  • 案例:

    • 假设当前配置是:

      • location /exact/match/test.html { 配置指令块1}

      • location /prefix/ { 配置指令块2}

      • location ~ \.html$ { 配置指令块3}

    • 请求URI:GET /prefix/index.html

      则会被匹配到:配置指令块3,因为普通location /prefix/依据最大匹配原则能匹配当前请求,但是会被后面的正则location覆盖

    • 请求URI:GET /exact/match/test.html

      则会被匹配到:配置指令块1,因为这个是普通location 的完全匹配(exact match),会禁止继续搜索正则location

正则location 匹配让步 普通location 的严格精确匹配结果,但覆盖 普通location 的最大前缀匹配结果

location 案例

  • 先普通 location ,再正则 location

    • nginx 其实是:先匹配普通 location ,再匹配正则 location 

    • 普通 location 的匹配结果又分两种

      • 一种是严格精确匹配(exact match)

      • 另一种是最大前缀匹配(Literal strings match the beginning portion of the query – the most specific match will be used)