|
1 | 1 | ## location 详解
|
2 | 2 |
|
3 |
| -#### 匹配顺序 |
| 3 | +### 匹配顺序 |
4 | 4 |
|
5 |
| -* location 的匹配顺序其实是**“先匹配普通,再匹配正则”**。 |
| 5 | +* location 的匹配顺序其实是`先匹配普通,再匹配正则` |
6 | 6 |
|
7 | 7 | * 正则匹配会覆盖普通匹配(实际的规则,比这复杂)
|
8 | 8 |
|
9 |
| -#### 执行顺序 |
| 9 | +### 执行顺序 |
10 | 10 |
|
11 |
| -* “普通 location ”的匹配规则是“最大前缀”,因此“普通 location ”的确与 location 编辑顺序无关。 |
| 11 | +* `普通 location`的匹配规则是“最大前缀”,`普通 location`与 location 编辑顺序无关。 |
12 | 12 |
|
13 |
| -* “正则 location ”的匹配规则是“顺序匹配,且只要匹配到第一个就停止后面的匹配”。 |
| 13 | +* `正则 location `的匹配规则是`顺序匹配,且只要匹配到第一个就停止后面的匹配` |
14 | 14 |
|
15 | 15 | * 两种情况下,不需要继续匹配正则 location
|
16 | 16 |
|
17 |
| - * (1)当普通 location 前面指定了`^~ `,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配。 |
18 |
| - * (2)当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。 |
| 17 | + * 当普通 location 前面指定了`^~ `,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配 |
19 | 18 |
|
20 |
| -* 正则 location 匹配让步普通 location 的严格精确匹配结果;但覆盖普通 location 的最大前缀匹配结果。 |
| 19 | + * 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。 |
21 | 20 |
|
22 |
| -#### 官方文档 |
| 21 | +* 正则 location 匹配让步普通 location 的严格精确匹配结果,但覆盖普通 location 的最大前缀匹配结果 |
| 22 | + |
| 23 | +### 官方文档 |
23 | 24 |
|
24 | 25 | * 语法
|
25 | 26 | ```bash
|
|
29 | 30 | context: server
|
30 | 31 | ```
|
31 | 32 | * 正则location `(location using regular expressions)`
|
| 33 | +
|
32 | 34 | * `~` 和 `~*` 前缀表示正则location
|
| 35 | +
|
33 | 36 | * `~` 区分大小写
|
| 37 | +
|
34 | 38 | * `~*` 不区分大小写
|
| 39 | +
|
35 | 40 | * 普通location `(location using literal strings)`
|
| 41 | +
|
36 | 42 | * 无任何前缀的都属于普通 location
|
| 43 | +
|
37 | 44 | * 其他前缀(包括:`=`、`^~` 和 `@`)也属于普通匹配
|
| 45 | +
|
38 | 46 | * 对于特定的HTTP请求`(a particular query)`,`nginx`应该匹配哪个`location`块的指令
|
39 |
| - * 原文:`To determine which location directive matches a particular query, the literal strings are checked first.` 先普通location再正则location |
| 47 | +
|
| 48 | + > 原文:`To determine which location directive matches a particular query, the literal strings are checked first.` 先普通location再正则location |
| 49 | +
|
40 | 50 | * `普通location` 与 `普通location` 是如何匹配的?
|
| 51 | +
|
41 | 52 | * 匹配规则1:先匹配普通location,再匹配正则location
|
| 53 | +
|
42 | 54 | * 匹配规则2:最大前缀匹配
|
| 55 | +
|
43 | 56 | * 匹配规则3:匹配`URI`的前缀部分`(match the beginning portion of the query)`
|
| 57 | +
|
44 | 58 | * 匹配规则4:最具体的匹配将被使用`(the most specific match will be used)`,因为 location 不是`严格匹配`,而是`前缀匹配`,就会产生一个HTTP 请求,可以`前缀匹配`到多个普通location
|
| 59 | +
|
45 | 60 | * 案例
|
| 61 | +
|
46 | 62 | * 列如:`location /prefix/mid/ {} `和`location /prefix/ {}`
|
| 63 | +
|
47 | 64 | * 于HTTP 请求`/prefix/mid/t.html`,前缀匹配的话两个`location`都满足,该匹配哪个?
|
| 65 | +
|
48 | 66 | * 匹配原则:最具体匹配原则`the most specific match`
|
| 67 | +
|
49 | 68 | * 最后的匹配是:`location /prefix/mid/ {}`
|
| 69 | +
|
50 | 70 | * `正则location` 与 `正则location` 是如何匹配的?
|
| 71 | +
|
51 | 72 | * 匹配规则是:按照 **正则location** 在配置文件中的物理顺序(编辑顺序)匹配
|
| 73 | +
|
52 | 74 | * 注意1:`location` 并不是一定跟顺序无关,只是**普通 location**与顺序无关,**正则 location**还是与顺序有关的
|
| 75 | +
|
53 | 76 | * `正则location`和`普通location`最大匹配如何匹配?
|
| 77 | +
|
54 | 78 | * 正则:**只要匹配到一条正则location ,就不再考虑后面匹配**
|
| 79 | +
|
55 | 80 | * 普通:**选择出“普通location”的最大前缀匹配结果后,还需要继续搜索正则location**
|
| 81 | +
|
56 | 82 | * `(普通)`最大前缀匹配结果与继续搜索的`正则location`匹配结果的决策关系
|
| 83 | +
|
57 | 84 | * 原文:`If no regular expression matches are found, the result from the literal string search is used.` 如果找不到正则表达式匹配,则使用文字字符串搜索的结果
|
58 |
| - * 匹配一:如果继续搜索的`正则location`也有匹配上的,那么`正则location`覆盖`普通location`的最大前缀匹配。 |
| 85 | +
|
| 86 | + * 匹配一:如果继续搜索的`正则location`也有匹配上的,那么`正则location`覆盖`普通location`的最大前缀匹配 |
| 87 | +
|
59 | 88 | * ~~因为有这个覆盖关系,所以造成有些同学以为正则location 先于普通location 执行的错误理解~~
|
| 89 | +
|
60 | 90 | * 但是如果“正则location ”没有能匹配上,那么就用“普通location ”的最大前缀匹配结果
|
| 91 | +
|
61 | 92 | * 一般匹配原则
|
| 93 | +
|
62 | 94 | * 匹配完了`普通location`指令,还需要继续匹配`正则location`
|
| 95 | +
|
63 | 96 | * 也可以告诉Nginx:匹配到了`普通location`后,不再需要继续匹配`正则location`了,
|
64 | 97 | >1.要做到这一点只要在`普通location`前面加上`^~`符号
|
65 | 98 | >2.`^` 表示`非`,`~` 表示`正则`,字符意思是:`不要继续匹配正则`
|
| 99 | +
|
66 | 100 | * `^~`和`=` 区别
|
| 101 | +
|
67 | 102 | * 共同点:都能阻止继续搜索`正则location`
|
| 103 | +
|
68 | 104 | * 不同点:
|
| 105 | +
|
69 | 106 | >1.`^~`依然遵守`最大前缀`匹配规则
|
70 | 107 | >2.`=`不是`最大前缀`,而是必须是严格匹配(exact match )
|
71 | 108 |
|
72 |
| -### 继续... |
| 109 | +#### `location / {} `和`location = / {}`的区别 |
| 110 | +
|
| 111 | +* `location / {}` |
| 112 | +
|
| 113 | + * 遵守的是:`普通location 的最大前缀匹配` |
| 114 | +
|
| 115 | + * 由于任何`URI`都必然以`/ `根开头,所以对于一个`URI`,如果有更具体(specific)的匹配,那自然是选这个更具体的匹配了,如果没有,`/`一定能为这个`URI`垫背(至少能匹配到`/`),可以说:`location / {}`有点像默认配置,其他更具体(specific)的配置能覆盖(overwrite)这个默认配置(这也是为什么总能看到`location / {}`这个配置的一个很重要的原因) |
| 116 | +
|
| 117 | +* `location = / {}` |
| 118 | +
|
| 119 | + * 遵守的是:`严格精确匹配exact match` |
| 120 | +
|
| 121 | + * 只能匹配`http://host:port/`请求,同时会禁止继续搜索`正则location` |
| 122 | +
|
| 123 | + * 因此如果我们只想对`GET / `请求配置作用指令,那么我们可以选`location = / {} `这样能减少正则location 的搜索,因此效率比`location / {}` 高 |
| 124 | +
|
| 125 | + > 注:前提是我们的目的仅仅只想对“GET / ”起作用 |
| 126 | +#### 精确匹配 |
| 127 | +
|
| 128 | +* `精确匹配exact match `,即使`普通location`没有带`=`或`^~`前缀,也一样会终止后面的匹配 |
| 129 | +
|
| 130 | +* 原文:`On exact match with literal location without “=” or “^~” prefixes search is also immediately terminated` |
| 131 | +
|
| 132 | +* 当`最大前缀`匹配恰好就是一个`严格精确(exact match )`匹配,照样会停止后面的搜索 |
| 133 | +
|
| 134 | +* 案例: |
| 135 | +
|
| 136 | + * 假设当前配置是: |
| 137 | +
|
| 138 | + * `location /exact/match/test.html { 配置指令块1}` |
| 139 | +
|
| 140 | + * `location /prefix/ { 配置指令块2}` |
| 141 | +
|
| 142 | + * `location ~ \.html$ { 配置指令块3}` |
| 143 | +
|
| 144 | + * 请求URI:`GET /prefix/index.html` |
| 145 | +
|
| 146 | + > 则会被匹配到:`配置指令块3`,因为`普通location /prefix/`依据最大匹配原则能匹配当前请求,但是会被后面的`正则location`覆盖 |
| 147 | +
|
| 148 | + * 请求URI:`GET /exact/match/test.html` |
| 149 | +
|
| 150 | + > 则会被匹配到:`配置指令块1`,因为这个是`普通location` 的完全匹配(exact match),会禁止继续搜索`正则location` |
| 151 | +
|
| 152 | +#### 正则location 匹配让步 普通location 的严格精确匹配结果,但覆盖 普通location 的最大前缀匹配结果 |
| 153 | +### location 案例 |
| 154 | +* 先普通 location ,再正则 location |
| 155 | +
|
| 156 | + * nginx 其实是:`先匹配普通 location ,再匹配正则 location ` |
| 157 | + |
| 158 | + * 普通 location 的匹配结果又分两种 |
| 159 | + |
| 160 | + * 一种是`严格精确匹配(exact match)` |
| 161 | + |
| 162 | + * 另一种是`最大前缀匹配(Literal strings match the beginning portion of the query – the most specific match will be used)` |
73 | 163 |
|
| 164 | +#### [http://www.cnblogs.com/lidabo/p/4169396.html](http://www.cnblogs.com/lidabo/p/4169396.html) |
0 commit comments