nginx location

关于一些对location认识的误区html

一、location 的匹配顺序是“先匹配正则,再匹配普通”。nginx

矫正: location 的匹配顺序实际上是“先匹配普通,再匹配正则”。我这么说,你们必定会反驳我,由于按“先匹配普通,再匹配正则”解释不了你们平时习惯的按“先匹配正则,再匹配普通”的实践经验。这里我只能暂时解释下,形成这种误解的缘由是:正则匹配会覆盖普通匹配(实际的规则,比这复杂,后面会详细解释)。正则表达式

二、 location 的执行逻辑跟 location 的编辑顺序无关。express

矫正:这句话不全对,“普通 location ”的匹配规则是“最大前缀”,所以“普通 location ”的确与 location 编辑顺序无关;可是“正则 location ”的匹配规则是“顺序匹配,且只要匹配到第一个就中止后面的匹配”;“普通location ”与“正则 location ”之间的匹配顺序是?先匹配普通 location ,再“考虑”匹配正则 location 。注意这里的“考虑”是“可能”的意思,也就是说匹配完“普通 location ”后,有的时候须要继续匹配“正则 location ”,有的时候则不须要继续匹配“正则 location ”。两种状况下,不须要继续匹配正则 location :( 1 )当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不须要继续正则匹配;( 2 )当普通location 刚好严格匹配上,不是最大前缀匹配,则再也不继续匹配正则。
浏览器


总结一句话:  “正则 location 匹配让步普通 location 的严格精确匹配结果;但覆盖普通 location 的最大前缀匹配结果”ide


官方文档解释this

REFER:  http://wiki.nginx.org/NginxHttpCoreModule#location编码

locationcode

syntax: location [=|~|~*|^~|@] /uri/ { … }orm

default: no

context: server

This directive allows different configurations depending on the URI.

(译者注:1 、different configurations depending on the URI 说的就是语法格式:location [=|~|~*|^~|@] /uri/ { … } ,依据不一样的前缀“= ”,“^~ ”,“~ ”,“~* ”和不带任何前缀的(由于[A] 表示可选,能够不要的),表达不一样的含义, 简单的说尽管location 的/uri/ 配置同样,但前缀不同,表达的是不一样的指令含义。2 、查询字符串不在URI范围内。例如:/films.htm?fid=123 的URI 是/films.htm 。)

It can be configured using both literal strings and regular expressions. To use regular expressions, you must use a prefix:

“~” for case sensitive matching

“~*” for case insensitive matching

译文:上文讲到location /uri/ 可经过使用不一样的前缀,表达不一样的含义。对这些不一样前缀,分下类,就2 大类:正则location ,英文说法是location using regular expressions 和普通location ,英文说法是location using literal strings 。那么其中“~ ”和“~* ”前缀表示正则location ,“~ ”区分大小写,“~* ”不区分大小写;其余前缀(包括:“=”,“^~ ”和“@ ”)和无任何前缀的都属于普通location 。


To determine which location directive matches a particular query, the literal strings are checked first.

译文:对于一个特定的 HTTP 请求( a particular query ), nginx 应该匹配哪一个 location 块的指令呢(注意:咱们在 nginx.conf 配置文件里面通常会定义多个 location 的)?匹配 规则是:先匹配普通location (再匹配正则表达式)。注意:官方文档这句话就明确说了,先普通location ,而不是有些同窗的误区“先匹配正则location ”。


Literal strings match the beginning portion of the query – the most specific match will be used.

前面说了“普通location ”与“正则location ”之间的匹配规则是:先匹配普通location ,再匹配正则location 。那么,“普通location ”内部(普通location 与普通location )是如何匹配的呢?简单的说:最大前缀匹配。原文:一、match the beginning portion of the query (说的是匹配URI 的前缀部分beginning portion ); 2 、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/ {} )。


Afterwards, regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search.

这段话说了两层意思,第一层是:“Afterwards, regular expressions are checked ”, 意思是普通location 先匹配,并且选择了最大前缀匹配后,不能就中止后面的匹配,最大前缀匹配只是一个临时的结果,nginx 还须要继续检查正则location (但至于最终才能普通location 的最大前缀匹配,仍是正则location 的匹配,截止当前的内容还没讲,但后面会讲)。第二层是“regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search. ”,意思是说“正则location ”与“正则location”内部的匹配规则是:按照正则location 在配置文件中的物理顺序(编辑顺序)匹配的(这句话就说明location 并非必定跟顺序无关,只是普通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 ”的最大前缀匹配结果。


For case insensitive operating systems, like Mac OS X or Windows with Cygwin, literal string matching is done in a case insensitive way (0.7.7). However, comparison is limited to single-byte locale’s only.

Regular expression may contain captures (0.7.40), which can then be used in other directives.

It is possible to disable regular expression checks after literal string matching by using “^~” prefix.If the most specific match literal location has this prefix: regular expressions aren’t checked.

一般的规则是,匹配完了“普通location ”指令,还须要继续匹配“正则location ”,可是你也能够告诉Nginx :匹配到了“普通location ”后,再也不须要继续匹配“正则location ”了,要作到这一点只要在“普通location ”前面加上“^~ ”符号(^ 表示“非”,~ 表示“正则”,字符意思是:不要继续匹配正则)。


By using the “=” prefix we define the exact match between request URI and location. When matched search stops immediately. E.g., if the request “/” occurs frequently, using “location = /” will speed up processing of this request a bit as search will stop after first comparison.

除了上文的“^~ ”能够阻止继续搜索正则location 外,你还能够加“= ”。那么若是“^~ ”和“= ”都能阻止继续搜索正则location 的话,那它们之间有什么区别呢?区别很简单,共同点是它们都能阻止继续搜索正则location ,不一样点是“^~ ”依然遵照“最大前缀”匹配规则,然而“= ”不是“最大前缀”,而是必须是严格匹配(exact match )。


这里顺便讲下“location / {} ”和“location = / {} ”的区别,“location / {} ”遵照普通location 的最大前缀匹配,因为任何URI 都必然以“/ ”根开头,因此对于一个URI ,若是有更specific 的匹配,那天然是选这个更specific 的,若是没有,“/ ”必定能为这个URI 垫背(至少能匹配到“/ ”),也就是说“location / {} ”有点默认配置的味道,其余更specific的配置能覆盖overwrite 这个默认配置(这也是为何咱们总能看到location / {} 这个配置的一个很重要的缘由)。而“location = / {} ”遵照的是“严格精确匹配exact match ”,也就是只能匹配 http://host:port/ 请求,同时会禁止继续搜索正则location 。所以若是咱们只想对“GET / ”请求配置做用指令,那么咱们能够选“location = / {} ”这样能减小正则location 的搜索,所以效率比“location / {}” 高(注:前提是咱们的目的仅仅只想对“GET / ”起做用)。


On exact match with literal location without “=” or “^~” prefixes search is also immediately terminated.

前面咱们说了,普通location 匹配完后,还会继续匹配正则location ;可是nginx 容许你阻止这种行为,方法很简单,只须要在普通location 前加“^~ ”或“= ”。但其实还有一种“隐含”的方式来阻止正则location 的搜索,这种隐含的方式就是:当“最大前缀”匹配刚好就是一个“严格精确(exact match )”匹配,照样会中止后面的搜索。原文字面意思是:只要遇到“精确匹配exact match ”,即便普通location 没有带“= ”或“^~ ”前缀,也同样会终止后面的匹配。


先举例解释下,后面例题会用实践告诉你们。假设当前配置是:location /exact/match/test.html { 配置指令块1},location /prefix/ { 配置指令块2} 和 location ~ \.html$ { 配置指令块3} ,若是咱们请求 GET /prefix/index.html ,则会被匹配到指令块3 ,由于普通location /prefix/ 依据最大匹配原则能匹配当前请求,可是会被后面的正则location 覆盖;当请求GET /exact/match/test.html ,会匹配到指令块1 ,由于这个是普通location 的exact match ,会禁止继续搜索正则location 。


To summarize, the order in which directives are checked is as follows:

Directives with the “=” prefix that match the query exactly. If found, searching stops.

All remaining directives with conventional strings. If this match used the “^~” prefix, searching stops.

Regular expressions, in the order they are defined in the configuration file.

If #3 yielded a match, that result is used. Otherwise, the match from #2 is used.

这个顺序不必再过多解释了。但我想用本身的话归纳下上面的意思“正则 location 匹配让步普通location 的严格精确匹配结果;但覆盖普通 location 的最大前缀匹配结果”。


It is important to know that nginx does the comparison against decoded URIs. For example, if you wish to match “/p_w_picpaths/ /test”, then you must use “/p_w_picpaths/ /test” to determine the location.


在浏览器上显示的URL 通常都会进行URLEncode ,例如“空格”会被编码为  ,可是Nginx 的URL 的匹配都是针对URLDecode 以后的。也就是说,若是你要匹配“/p_w_picpaths/ /test ”,你写location 的时候匹配目标应该是:“/p_w_picpaths/ /test ”。


Example:

location   = / {

 # matches the query / only.

 [ configuration A ]

}


location   / {

  # matches any query, since all queries begin with /, but regular

  # expressions and any longer conventional blocks will be

  # matched first.

 [ configuration B ]

}


location ^~ /p_w_picpaths/ {

 # matches any query beginning with /p_w_picpaths/ and halts searching,

 # so regular expressions will not be checked.

 [ configuration C ]

}


location ~* \.(gif|jpg|jpeg)$ {

 # matches any request ending in gif, jpg, or jpeg. However, all

 # requests to the /p_w_picpaths/ directory will be handled by

 # Configuration C.  

 [ configuration D ]

}

上述这4 个location 的配置,没什么好解释的,惟一须要说明的是location / {[configuration B]} ,原文的注释严格来讲是错误的,但我相信原文做者是了解规则的,只是文字描述上简化了下,但这个简化容易给读者形成“误解:先检查正则location ,再检查普通location ”。原文:“matches any query, since all queries begin with /, butregular expressions and any longer conventional blocks will be matched first. ”大意是说:“location / {} 可以匹配全部HTTP 请求,由于任何HTTP 请求都必然是以‘/ ’开始的(这半句没有错误)。可是,正则location 和其余任何比‘/ ’更长的普通location (location / {} 是普通location 里面最短的,所以其余任何普通location 都会比它更长,固然location = / {} 和 location ^~ / {} 是同样长的)会优先匹配(matched first )。” 原文做者说“ but regular expressions will be matched first. ”应该只是想说正则 location 会覆盖这里的 location / {} ,但依然是普通location / {} 先于正则 location 匹配,接着再正则 location 匹配;但其余更长的普通 location ( any longer conventional blocks )的确会先于 location / {} 匹配。


Example requests:

/ -> configuration A

/documents/document.html -> configuration B

/p_w_picpaths/1.gif -> configuration C

/documents/1.jpg -> configuration D

Note that you could define these 4 configurations in any order and the results would remain the same.

须要提醒下:这里说“in any order ”和“… remain the same ”是由于上面只有一个正则location 。文章前面已经说了正则location 的匹配是跟编辑顺序有关系的。


While nested locations are allowed by the configuration file parser, their use is discouraged and may produce unexpected results.

实际上 nginx 的配置文件解析程序是容许 location 嵌套定义的( location / { location /uri/ {} } )。可是咱们平时却不多看见这样的配置,那是由于 nginx 官方并不建议你们这么作,由于这样会致使不少意想不到的后果。


The prefix “@” specifies a named location. Such locations are not used during normal processing of requests, they are intended only to process internally redirected requests (see error_page ,try_files ).

文章开始说了location 的语法中,能够有“= ”,“^~ ”,“~ ”和“~* ”前缀,或者干脆没有任何前缀,还有“@ ”前缀,可是后面的分析咱们始终没有谈到“@ ”前缀。文章最后点内容,介绍了“@”的用途:“@ ”是用来定义“Named Location ”的(你能够理解为独立于“普通location (location using literal strings )”和“正则location (location using regular expressions )”以外的第三种类型),这种“Named Location ”不是用来处理普通的HTTP 请求的,它是专门用来处理“内部重定向(internally redirected )”请求的。注意:这里说的“内部重定向(internally redirected )”或许说成“forward ”会好点,觉得内internally redirected 是不须要跟浏览器交互的,纯粹是服务端的一个转发行为。


http://www.cnblogs.com/lidabo/p/4169396.html

相关文章
相关标签/搜索