第三講 nginx的location模塊

本章主要內(nèi)容是nginx的location模塊,也是最重要的模塊。

location模塊:

  • proxy_set_header
    nginx是通過(guò)proxy_set_header來(lái)設(shè)置請(qǐng)求頭,它的語(yǔ)法如下:
    proxy_set_header field value;
    默認(rèn)值:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;

其他一些有用的值:

 proxy_set_header X-Real-IP $remote_addr;#配置這個(gè)之后可以通過(guò) request.getAttribute("X-real-ip"),來(lái)獲客戶端取真實(shí)的ip
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
官方文檔解釋

REFER: http://wiki.nginx.org/NginxHttpCoreModule#location
location
syntax:location [=|||^~|@] /uri/ { … }
default:no
context:server
This directive allows different configurations depending on the URI.

(譯者注:1 、different configurations depending on the URI 說(shuō)的就是語(yǔ)法格式:location [=|||^~|@] /uri/ { … } ,依據(jù)不同的前綴“= ”,“^~ ”,“~ ”,“~ ”和不帶任何前綴的(因?yàn)閇A] 表示可選,可以不要的),表達(dá)不同的含義, 簡(jiǎn)單的說(shuō)盡管location 的/uri/ 配置一樣,但前綴不一樣,表達(dá)的是不同的指令含義。2 、查詢字符串不在URI范圍內(nèi)。例如:/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:

  1. “~” for case sensitive matching
  2. “~*” for case insensitive matching

譯文:上文講到location /uri/ 可通過(guò)使用不同的前綴,表達(dá)不同的含義。對(duì)這些不同前綴,分下類,就2 大類:正則location ,英文說(shuō)法是location using regular expressions 和普通location ,英文說(shuō)法是location using literal strings 。那么其中“~ ”和“~* ”前綴表示正則location ,“~ ”區(qū)分大小寫,“~* ”不區(qū)分大小寫;其他前綴(包括:“=”,“^~ ”和“@ ”)和無(wú)任何前綴的都屬于普通location 。

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

譯文:對(duì)于一個(gè)特定的 HTTP 請(qǐng)求( a particular query ), nginx 應(yīng)該匹配哪個(gè) location 塊的指令呢(注意:我們?cè)?nginx.conf 配置文件里面一般會(huì)定義多個(gè) location 的)?匹配 規(guī)則是:先匹配普通location (再匹配正則表達(dá)式)。注意:官方文檔這句話就明確說(shuō)了,先普通location ,而不是有些同學(xué)的誤區(qū)“先匹配正則location ”。

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

前面說(shuō)了“普通location ”與“正則location ”之間的匹配規(guī)則是:先匹配普通location ,再匹配正則location 。那么,“普通location ”內(nèi)部(普通location 與普通location )是如何匹配的呢?簡(jiǎn)單的說(shuō):最大前綴匹配。原文:1、match the beginning portion of the query (說(shuō)的是匹配URI 的前綴部分beginning portion ); 2 、the most specific match will be used (因?yàn)閘ocation 不是“嚴(yán)格匹配”,而是“前綴匹配”,就會(huì)產(chǎn)生一個(gè)HTTP 請(qǐng)求,可以“前綴匹配”到多個(gè)普通location ,例如:location /prefix/mid/ {} 和location /prefix/ {} ,對(duì)于HTTP 請(qǐng)求/prefix/mid/t.html ,前綴匹配的話兩個(gè)location 都滿足,選哪個(gè)?原則是: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.

這段話說(shuō)了兩層意思,第一層是:“Afterwards, regular expressions are checked ”, 意思是普通location 先匹配,而且選擇了最大前綴匹配后,不能就停止后面的匹配,最大前綴匹配只是一個(gè)臨時(shí)的結(jié)果,nginx 還需要繼續(xù)檢查正則location (但至于最終才能普通location 的最大前綴匹配,還是正則location 的匹配,截止當(dāng)前的內(nèi)容還沒(méi)講,但后面會(huì)講)。第二層是“regular expressions are checked in the order defined in the configuration file. The first regular expression to match the query will stop the search. ”,意思是說(shuō)“正則location ”與“正則location”內(nèi)部的匹配規(guī)則是:按照正則location 在配置文件中的物理順序(編輯順序)匹配的(這句話就說(shuō)明location 并不是一定跟順序無(wú)關(guān),只是普通location 與順序無(wú)關(guān),正則location 還是與順序有關(guān)的),并且只要匹配到一條正則location ,就不再考慮后面的(這與“普通location ”與“正則location ”之間的規(guī)則不一樣,“普通location ”與“正則location ”之間的規(guī)則是:選擇出“普通location ”的最大前綴匹配結(jié)果后,還需要繼續(xù)搜索正則location )。

If no regular expression matches are found, the result from the literal string search is used.

這句話回答了“普通location ”的最大前綴匹配結(jié)果與繼續(xù)搜索的“正則location ”匹配結(jié)果的決策關(guān)系。如果繼續(xù)搜索的“正則location ”也有匹配上的,那么“正則location ”覆蓋 “普通location ”的最大前綴匹配(因?yàn)橛羞@個(gè)覆蓋關(guān)系,所以造成有些同學(xué)以為正則location 先于普通location 執(zhí)行的錯(cuò)誤理解);但是如果“正則location ”沒(méi)有能匹配上,那么就用“普通location ”的最大前綴匹配結(jié)果。

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.

通常的規(guī)則是,匹配完了“普通location ”指令,還需要繼續(xù)匹配“正則location ”,但是你也可以告訴Nginx :匹配到了“普通location ”后,不再需要繼續(xù)匹配“正則location ”了,要做到這一點(diǎn)只要在“普通location ”前面加上“^~ ”符號(hào)(^ 表示“非”,~ 表示“正則”,字符意思是:不要繼續(xù)匹配正則)。

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 “l(fā)ocation = /” will speed up processing of this request a bit as search will stop after first comparison.

除了上文的“^~ ”可以阻止繼續(xù)搜索正則location 外,你還可以加“= ”。那么如果“^~ ”和“= ”都能阻止繼續(xù)搜索正則location 的話,那它們之間有什么區(qū)別呢?區(qū)別很簡(jiǎn)單,共同點(diǎn)是它們都能阻止繼續(xù)搜索正則location ,不同點(diǎn)是“^~ ”依然遵守“最大前綴”匹配規(guī)則,然而“= ”不是“最大前綴”,而是必須是嚴(yán)格匹配(exact match )。

這里順便講下“l(fā)ocation / {} ”和“l(fā)ocation = / {} ”的區(qū)別,“l(fā)ocation / {} ”遵守普通location 的最大前綴匹配,由于任何URI 都必然以“/ ”根開(kāi)頭,所以對(duì)于一個(gè)URI ,如果有更specific 的匹配,那自然是選這個(gè)更specific 的,如果沒(méi)有,“/ ”一定能為這個(gè)URI 墊背(至少能匹配到“/ ”),也就是說(shuō)“l(fā)ocation / {} ”有點(diǎn)默認(rèn)配置的味道,其他更specific的配置能覆蓋overwrite 這個(gè)默認(rèn)配置(這也是為什么我們總能看到location / {} 這個(gè)配置的一個(gè)很重要的原因)。而“l(fā)ocation = / {} ”遵守的是“嚴(yán)格精確匹配exact match ”,也就是只能匹配 http://host:port/ 請(qǐng)求,同時(shí)會(huì)禁止繼續(xù)搜索正則location 。因此如果我們只想對(duì)“GET / ”請(qǐng)求配置作用指令,那么我們可以選“l(fā)ocation = / {} ”這樣能減少正則location 的搜索,因此效率比“l(fā)ocation / {}” 高(注:前提是我們的目的僅僅只想對(duì)“GET / ”起作用)。

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

前面我們說(shuō)了,普通location 匹配完后,還會(huì)繼續(xù)匹配正則location ;但是nginx 允許你阻止這種行為,方法很簡(jiǎn)單,只需要在普通location 前加“^~ ”或“= ”。但其實(shí)還有一種“隱含”的方式來(lái)阻止正則location 的搜索,這種隱含的方式就是:當(dāng)“最大前綴”匹配恰好就是一個(gè)“嚴(yán)格精確(exact match )”匹配,照樣會(huì)停止后面的搜索。原文字面意思是:只要遇到“精確匹配exact match ”,即使普通location 沒(méi)有帶“= ”或“^~ ”前綴,也一樣會(huì)終止后面的匹配。

先舉例解釋下,后面例題會(huì)用實(shí)踐告訴大家。假設(shè)當(dāng)前配置是:location /exact/match/test.html { 配置指令塊1},location /prefix/ { 配置指令塊2} 和 location ~ .html$ { 配置指令塊3} ,如果我們請(qǐng)求 GET /prefix/index.html ,則會(huì)被匹配到指令塊3 ,因?yàn)槠胀╨ocation /prefix/ 依據(jù)最大匹配原則能匹配當(dāng)前請(qǐng)求,但是會(huì)被后面的正則location 覆蓋;當(dāng)請(qǐng)求GET /exact/match/test.html ,會(huì)匹配到指令塊1 ,因?yàn)檫@個(gè)是普通location 的exact match ,會(huì)禁止繼續(xù)搜索正則location 。

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

  1. Directives with the “=” prefix that match the query exactly. If found, searching stops.
  2. All remaining directives with conventional strings. If this match used the “^~” prefix, searching stops.
  3. Regular expressions, in the order they are defined in the configuration file.
  4. If #3 yielded a match, that result is used. Otherwise, the match from #2 is used.

這個(gè)順序沒(méi)必要再過(guò)多解釋了。但我想用自己的話概括下上面的意思“正則 location 匹配讓步普通location 的嚴(yán)格精確匹配結(jié)果;但覆蓋普通 location 的最大前綴匹配結(jié)果”。

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

在瀏覽器上顯示的URL 一般都會(huì)進(jìn)行URLEncode ,例如“空格”會(huì)被編碼為 ,但是Nginx 的URL 的匹配都是針對(duì)URLDecode 之后的。也就是說(shuō),如果你要匹配“/images/ /test ”,你寫location 的時(shí)候匹配目標(biāo)應(yīng)該是:“/images/ /test ”。

Example:
location

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  ^~ /images/ {
  #matches any query beginning with /images/ 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 /images/ directory will be handled by
 # Configuration C.  
 [ configuration D ]
}

上述這4 個(gè)location 的配置,沒(méi)什么好解釋的,唯一需要說(shuō)明的是location / {[configuration B]} ,原文的注釋嚴(yán)格來(lái)說(shuō)是錯(cuò)誤的,但我相信原文作者是了解規(guī)則的,只是文字描述上簡(jiǎn)化了下,但這個(gè)簡(jiǎn)化容易給讀者造成“誤解:先檢查正則location ,再檢查普通location ”。原文:“matches any query, since all queries begin with /, but regular expressions and any longer conventional blocks **will be matched first. ”大意是說(shuō):“l(fā)ocation / {} 能夠匹配所有HTTP 請(qǐng)求,因?yàn)槿魏蜨TTP 請(qǐng)求都必然是以‘/ ’開(kāi)始的(這半句沒(méi)有錯(cuò)誤)。但是,正則location 和其他任何比‘/ ’更長(zhǎng)的普通location (location / {} 是普通location 里面最短的,因此其他任何普通location 都會(huì)比它更長(zhǎng),當(dāng)然location = / {} 和 location ^~ / {} 是一樣長(zhǎng)的)會(huì)優(yōu)先匹配(matched first )?!?**原文作者說(shuō)“ but regular expressions will be matched first. ”應(yīng)該只是想說(shuō)正則 location 會(huì)覆蓋這里的 location / {} ,但依然是普通location / {} 先于正則 location 匹配,接著再正則 location 匹配;但其他更長(zhǎng)的普通 location ( any longer conventional blocks )的確會(huì)先于 location / {} 匹配。

Example requests:

  • / -> configuration A
  • /documents/document.html -> configuration B
  • /images/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.

需要提醒下:這里說(shuō)“in any order ”和“… remain the same ”是因?yàn)樯厦嬷挥幸粋€(gè)正則location 。文章前面已經(jīng)說(shuō)了正則location 的匹配是跟編輯順序有關(guān)系的。

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

實(shí)際上 nginx 的配置文件解析程序是允許 location 嵌套定義的( location / { location /uri/ {} } )。但是我們平時(shí)卻很少看見(jiàn)這樣的配置,那是因?yàn)?nginx 官方并不建議大家這么做,因?yàn)檫@樣會(huì)導(dǎo)致很多意想不到的后果。

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 **).

文章開(kāi)始說(shuō)了location 的語(yǔ)法中,可以有“= ”,“^~ ”,“~ ”和“~* ”前綴,或者干脆沒(méi)有任何前綴,還有“@ ”前綴,但是后面的分析我們始終沒(méi)有談到“@ ”前綴。文章最后點(diǎn)內(nèi)容,介紹了“@”的用途:“@ ”是用來(lái)定義“Named Location ”的(你可以理解為獨(dú)立于“普通location (location using literal strings )”和“正則location (location using regular expressions )”之外的第三種類型),這種“Named Location ”不是用來(lái)處理普通的HTTP 請(qǐng)求的,它是專門用來(lái)處理“內(nèi)部重定向(internally redirected )”請(qǐng)求的。注意:這里說(shuō)的“內(nèi)部重定向(internally redirected )”或許說(shuō)成“forward ”會(huì)好點(diǎn),以為內(nèi)internally redirected 是不需要跟瀏覽器交互的,純粹是服務(wù)端的一個(gè)轉(zhuǎn)發(fā)行為。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • location匹配命令~ #波浪線表示執(zhí)行一個(gè)正則匹配,區(qū)分大小寫~* #表示執(zhí)行一個(gè)正則匹配,...
    柏樹_Jeff閱讀 636評(píng)論 0 0
  • 前言 最先接觸編程的知識(shí)是在大學(xué)里面,大學(xué)里面學(xué)了一些基礎(chǔ)的知識(shí),c語(yǔ)言,java語(yǔ)言,單片機(jī)的匯編語(yǔ)言等;大學(xué)畢...
    oceanfive閱讀 3,368評(píng)論 0 7
  • 1.簡(jiǎn)介: ? Nginx:engine X ,2002年,開(kāi)源,商業(yè)版? http協(xié)議:web服務(wù)器(類似于ht...
    尛尛大尹閱讀 2,000評(píng)論 0 3
  • 已經(jīng)同步到gitbook,想閱讀的請(qǐng)轉(zhuǎn)到gitbook: Django 1.10 中文文檔 URL dispatc...
    leyu閱讀 14,417評(píng)論 0 16

友情鏈接更多精彩內(nèi)容