Nginx之location 匹配规则详解.docx

上传人:b****7 文档编号:8955383 上传时间:2023-02-02 格式:DOCX 页数:19 大小:26.87KB
下载 相关 举报
Nginx之location 匹配规则详解.docx_第1页
第1页 / 共19页
Nginx之location 匹配规则详解.docx_第2页
第2页 / 共19页
Nginx之location 匹配规则详解.docx_第3页
第3页 / 共19页
Nginx之location 匹配规则详解.docx_第4页
第4页 / 共19页
Nginx之location 匹配规则详解.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

Nginx之location 匹配规则详解.docx

《Nginx之location 匹配规则详解.docx》由会员分享,可在线阅读,更多相关《Nginx之location 匹配规则详解.docx(19页珍藏版)》请在冰豆网上搜索。

Nginx之location 匹配规则详解.docx

Nginx之location匹配规则详解

关于一些对location认识的误区

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

矫正:

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

我这么说,大家一定会反驳我,因为按“先匹配普通,再匹配正则”解释不了大家平时习惯的按“先匹配正则,再匹配普通”的实践经验。

这里我只能暂时解释下,造成这种误解的原因是:

正则匹配会覆盖普通匹配(实际的规则,比这复杂,后面会详细解释)。

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

矫正:

这句话不全对,“普通location”的匹配规则是“最大前缀”,因此“普通location”的确与location编辑顺序无关;但是“正则location”的匹配规则是“顺序匹配,且只要匹配到第一个就停止后面的匹配”;“普通location”与“正则location”之间的匹配顺序是?

先匹配普通location,再“考虑”匹配正则location。

注意这里的“考虑”是“可能”的意思,也就是说匹配完“普通location”后,有的时候需要继续匹配“正则location”,有的时候则不需要继续匹配“正则location”。

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

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

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

总结一句话:

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

官方文档解释

REFER:

http:

//wiki.nginx.org/NginxHttpCoreModule#location

location

syntax:

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

default:

no

context:

server

ThisdirectiveallowsdifferentconfigurationsdependingontheURI.

(译者注:

1、differentconfigurationsdependingontheURI说的就是语法格式:

location[=|~|~*|^~|@]/uri/{…},依据不同的前缀“=”,“^~”,“~”,“~*”和不带任何前缀的(因为[A]表示可选,可以不要的),表达不同的含义,简单的说尽管location的/uri/配置一样,但前缀不一样,表达的是不同的指令含义。

2、查询字符串不在URI范围内。

例如:

/films.htm?

fid=123的URI是/films.htm。

Itcanbeconfiguredusingbothliteralstringsandregularexpressions.Touseregularexpressions,youmustuseaprefix:

1.“~”forcasesensitivematching

2.“~*”forcaseinsensitivematching

译文:

上文讲到location/uri/可通过使用不同的前缀,表达不同的含义。

对这些不同前缀,分下类,就2大类:

正则location,英文说法是locationusingregularexpressions和普通location,英文说法是locationusingliteralstrings。

那么其中“~”和“~*”前缀表示正则location,“~”区分大小写,“~*”不区分大小写;其他前缀(包括:

“=”,“^~”和“@”)和无任何前缀的都属于普通location。

Todeterminewhichlocationdirectivematchesaparticularquery,theliteralstringsarecheckedfirst.

译文:

对于一个特定的HTTP请求(aparticularquery),nginx应该匹配哪个location块的指令呢(注意:

我们在nginx.conf配置文件里面一般会定义多个location的)?

匹配规则是:

先匹配普通location(再匹配正则表达式)。

注意:

官方文档这句话就明确说了,先普通location,而不是有些同学的误区“先匹配正则location”。

Literalstringsmatchthebeginningportionofthequery–themostspecificmatchwillbeused.

前面说了“普通location”与“正则location”之间的匹配规则是:

先匹配普通location,再匹配正则location。

那么,“普通location”内部(普通location与普通location)是如何匹配的呢?

简单的说:

最大前缀匹配。

原文:

1、matchthebeginningportionofthequery(说的是匹配URI的前缀部分beginningportion);2、themostspecificmatchwillbeused(因为location不是“严格匹配”,而是“前缀匹配”,就会产生一个HTTP请求,可以“前缀匹配”到多个普通location,例如:

location/prefix/mid/{}和location/prefix/{},对于HTTP请求/prefix/mid/t.html,前缀匹配的话两个location都满足,选哪个?

原则是:

themostspecificmatch,于是选的是location/prefix/mid/{})。

Afterwards,regularexpressionsarecheckedintheorderdefinedintheconfigurationfile.Thefirstregularexpressiontomatchthequerywillstopthesearch.

这段话说了两层意思,第一层是:

“Afterwards,regularexpressionsarechecked”,意思是普通location先匹配,而且选择了最大前缀匹配后,不能就停止后面的匹配,最大前缀匹配只是一个临时的结果,nginx还需要继续检查正则location(但至于最终才能普通location的最大前缀匹配,还是正则location的匹配,截止当前的内容还没讲,但后面会讲)。

第二层是“regularexpressionsarecheckedintheorderdefinedintheconfigurationfile.Thefirstregularexpressiontomatchthequerywillstopthesearch.”,意思是说“正则location”与“正则location”内部的匹配规则是:

按照正则location在配置文件中的物理顺序(编辑顺序)匹配的(这句话就说明location并不是一定跟顺序无关,只是普通location与顺序无关,正则location还是与顺序有关的),并且只要匹配到一条正则location,就不再考虑后面的(这与“普通location”与“正则location”之间的规则不一样,“普通location”与“正则location”之间的规则是:

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

Ifnoregularexpressionmatchesarefound,theresultfromtheliteralstringsearchisused.

这句话回答了“普通location”的最大前缀匹配结果与继续搜索的“正则location”匹配结果的决策关系。

如果继续搜索的“正则location”也有匹配上的,那么“正则location”覆盖“普通location”的最大前缀匹配(因为有这个覆盖关系,所以造成有些同学以为正则location先于普通location执行的错误理解);但是如果“正则location”没有能匹配上,那么就用“普通location”的最大前缀匹配结果。

Forcaseinsensitiveoperatingsystems,likeMacOSXorWindowswithCygwin,literalstringmatchingisdoneinacaseinsensitiveway(0.7.7).However,comparisonislimitedtosingle-bytelocale’sonly.

Regularexpressionmaycontaincaptures(0.7.40),whichcanthenbeusedinotherdirectives.

Itispossibletodisableregularexpressionchecksafterliteralstringmatchingbyusing“^~”prefix.Ifthemostspecificmatchliterallocationhasthisprefix:

regularexpressionsaren’tchecked.

通常的规则是,匹配完了“普通location”指令,还需要继续匹配“正则location”,但是你也可以告诉Nginx:

匹配到了“普通location”后,不再需要继续匹配“正则location”了,要做到这一点只要在“普通location”前面加上“^~”符号(^表示“非”,~表示“正则”,字符意思是:

不要继续匹配正则)。

Byusingthe“=”prefixwedefinetheexactmatchbetweenrequestURIandlocation.Whenmatchedsearchstopsimmediately.E.g.,iftherequest“/”occursfrequently,using“location=/”willspeedupprocessingofthisrequestabitassearchwillstopafterfirstcomparison.

除了上文的“^~”可以阻止继续搜索正则location外,你还可以加“=”。

那么如果“^~”和“=”都能阻止继续搜索正则location的话,那它们之间有什么区别呢?

区别很简单,共同点是它们都能阻止继续搜索正则location,不同点是“^~”依然遵守“最大前缀”匹配规则,然而“=”不是“最大前缀”,而是必须是严格匹配(exactmatch)。

这里顺便讲下“location/{}”和“location=/{}”的区别,“location/{}”遵守普通location的最大前缀匹配,由于任何URI都必然以“/”根开头,所以对于一个URI,如果有更specific的匹配,那自然是选这个更specific的,如果没有,“/”一定能为这个URI垫背(至少能匹配到“/”),也就是说“location/{}”有点默认配置的味道,其他更specific的配置能覆盖overwrite这个默认配置(这也是为什么我们总能看到location/{}这个配置的一个很重要的原因)。

而“location=/{}”遵守的是“严格精确匹配exactmatch”,也就是只能匹配http:

//host:

port/请求,同时会禁止继续搜索正则location。

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

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

Onexactmatchwithliterallocationwithout“=”or“^~”prefixessearchisalsoimmediatelyterminated.

前面我们说了,普通location匹配完后,还会继续匹配正则location;但是nginx允许你阻止这种行为,方法很简单,只需要在普通location前加“^~”或“=”。

但其实还有一种“隐含”的方式来阻止正则location的搜索,这种隐含的方式就是:

当“最大前缀”匹配恰好就是一个“严格精确(exactmatch)”匹配,照样会停止后面的搜索。

原文字面意思是:

只要遇到“精确匹配exactmatch”,即使普通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的exactmatch,会禁止继续搜索正则location。

Tosummarize,theorderinwhichdirectivesarecheckedisasfollows:

1.Directiveswiththe“=”prefixthatmatchthequeryexactly.Iffound,searchingstops.

2.Allremainingdirectiveswithconventionalstrings.Ifthismatchusedthe“^~”prefix,searchingstops.

3.Regularexpressions,intheordertheyaredefinedintheconfigurationfile.

4.If#3yieldedamatch,thatresultisused.Otherwise,thematchfrom#2isused.

这个顺序没必要再过多解释了。

但我想用自己的话概括下上面的意思“正则location匹配让步普通location的严格精确匹配结果;但覆盖普通location的最大前缀匹配结果”。

ItisimportanttoknowthatnginxdoesthecomparisonagainstdecodedURIs.Forexample,ifyouwishtomatch“/images//test”,thenyoumustuse“/images//test”todeterminethelocation.

在浏览器上显示的URL一般都会进行URLEncode,例如“空格”会被编码为,但是Nginx的URL的匹配都是针对URLDecode之后的。

也就是说,如果你要匹配“/images//test”,你写location的时候匹配目标应该是:

“/images//test”。

Example:

location=/{

#matchesthequery/only.

[configurationA]

}

location/{

#matchesanyquery,sinceallqueriesbeginwith/,butregular

#expressionsandanylongerconventionalblockswillbe

#matchedfirst.

[configurationB]

}

location^~/images/{

#matchesanyquerybeginningwith/images/andhaltssearching,

#soregularexpressionswillnotbechecked.

[configurationC]

}

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

#matchesanyrequestendingingif,jpg,orjpeg.However,all

#requeststothe/images/directorywillbehandledby

#ConfigurationC.

[configurationD]

}

上述这4个location的配置,没什么好解释的,唯一需要说明的是location/{[configurationB]},原文的注释严格来说是错误的,但我相信原文作者是了解规则的,只是文字描述上简化了下,但这个简化容易给读者造成“误解:

先检查正则location,再检查普通location”。

原文:

“matchesanyquery,sinceallqueriesbeginwith/,butregularexpressionsandanylongerconventionalblockswillbematchedfirst.”大意是说:

“location/{}能够匹配所有HTTP请求,因为任何HTTP请求都必然是以‘/’开始的(这半句没有错误)。

但是,正则location和其他任何比‘/’更长的普通location(location/{}是普通location里面最短的,因此其他任何普通location都会比它更长,当然location=/{}和location^~/{}是一样长的)会优先匹配(matchedfirst)。

”原文作者说“butregularexpressionswillbematchedfirst.”应该只是想说正则location会覆盖这里的location/{},但依然是普通location/{}先于正则location匹配,接着再正则location匹配;但其他更长的普通location(anylongerconventionalblocks)的确会先于location/{}匹配。

Examplerequests:

∙/->configurationA

∙/documents/document.html->configurationB

∙/images/1.gif->configurationC

∙/documents/1.jpg->configurationD

Notethatyoucoulddefinethese4configurationsinanyorderandtheresultswouldremainthesame.

需要提醒下:

这里说“inanyorder”和“…remainthesame”是因为上面只有一个正则location。

文章前面已经说了正则location的匹配是跟编辑顺序有关系的。

Whilenestedlocationsareallowedbytheconfigurationfileparser,theiruseisdiscouragedandmayproduceunexpectedresults.

实际上nginx的配置文件解析程序是允许location嵌套定义的(location/{location/uri/{}})。

但是我们平时却很少看见这样的配置,那是因为nginx官方并不建议大家这么做,因为这样会导致很多意想不到的后果。

Theprefix“@”specifiesanamedlocation.Suchlocationsarenotusedduringnormalprocessingofrequests,theyareintendedonlytoprocessinternallyredirectedrequests(seeerror_page,try_files).

文章开始说了location的语法中,可以有“=”,“^~”,“~”和“~*”前缀,或者干脆没有任何前缀,还有“@”前缀,但是后面的分析我们始终没有谈到“@”前缀。

文章最后点内容,介绍了“@”的用途:

“@”是用来定义“NamedLocation”的(你可以理解为独立于“普通location(locationusingliteralstrings)”和“正则location(locationusingregularexpressions)”之外的第三种类型),这种“NamedLocation”不是用来处理普通的HTTP请求的,它是专门用来处理“内部重定向(internallyredirected)”请求的。

注意:

这里说的“内部重定向(internallyredirected)”或许说成“forward”会好点,以为内internallyredirected是不需要跟浏览器交互的,纯粹是服务端的一个转发行为。

安装Nginx

wgethttp:

//nginx.org/download/nginx-1.4.6.tar.gz

tarzxvfnginx-1.1.0.tar.gz

./configure

make

makeinstall

需要注意的是在configure这步遇到点小麻烦:

./configure:

error:

theHTTPrewritemodulerequiresthePCRElibrary.

安装nginx的时候,rewrite模块默认是需要被安装的。

但是rewrite模块所依赖的PCRE库需要额外安装。

Youcaneitherdisablethemodulebyusing–without-http_rewrite_module

option,orinstall

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1