本章主要內(nèi)容是nginx的location模塊晨抡,也是最重要的模塊。
location模塊:
- proxy_set_header
nginx是通過proxy_set_header來設(shè)置請(qǐng)求頭迷守,它的語法如下:
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è)之后可以通過 request.getAttribute("X-real-ip"),來獲客戶端取真實(shí)的ip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- location 的語法和匹配原則(轉(zhuǎn)載自https://www.cnblogs.com/lidabo/p/4169396.html)
官方文檔解釋
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 說的就是語法格式:location [=|||^~|@] /uri/ { … } ,依據(jù)不同的前綴“= ”梨树,“^~ ”,“~ ”岖寞,“~ ”和不帶任何前綴的(因?yàn)閇A] 表示可選抡四,可以不要的),表達(dá)不同的含義, 簡(jiǎn)單的說盡管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:
- “~” for case sensitive matching
- “~*” for case insensitive matching
譯文:上文講到location /uri/ 可通過使用不同的前綴岁疼,表達(dá)不同的含義阔涉。對(duì)這些不同前綴,分下類捷绒,就2 大類:正則location 瑰排,英文說法是location using regular expressions 和普通location ,英文說法是location using literal strings 暖侨。那么其中“~ ”和“~* ”前綴表示正則location 椭住,“~ ”區(qū)分大小寫,“~* ”不區(qū)分大小寫字逗;其他前綴(包括:“=”京郑,“^~ ”和“@ ”)和無任何前綴的都屬于普通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á)式)。注意:官方文檔這句話就明確說了俭厚,先普通location 户魏,而不是有些同學(xué)的誤區(qū)“先匹配正則location ”。
Literal strings match the beginning portion of the query – the most specific match will be used.
前面說了“普通location ”與“正則location ”之間的匹配規(guī)則是:先匹配普通location 挪挤,再匹配正則location 叼丑。那么,“普通location ”內(nèi)部(普通location 與普通location )是如何匹配的呢?簡(jiǎn)單的說:最大前綴匹配。原文:1睛廊、match the beginning portion of the query (說的是匹配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.
這段話說了兩層意思琳袄,第一層是:“Afterwards, regular expressions are checked ”, 意思是普通location 先匹配,而且選擇了最大前綴匹配后纺酸,不能就停止后面的匹配窖逗,最大前綴匹配只是一個(gè)臨時(shí)的結(jié)果,nginx 還需要繼續(xù)檢查正則location (但至于最終才能普通location 的最大前綴匹配餐蔬,還是正則location 的匹配碎紊,截止當(dāng)前的內(nè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. ”仗考,意思是說“正則location ”與“正則location”內(nèi)部的匹配規(guī)則是:按照正則location 在配置文件中的物理順序(編輯順序)匹配的(這句話就說明location 并不是一定跟順序無關(guān),只是普通location 與順序無關(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 ”沒有能匹配上顾画,那么就用“普通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 都必然以“/ ”根開頭秀睛,所以對(duì)于一個(gè)URI 尔当,如果有更specific 的匹配,那自然是選這個(gè)更specific 的琅催,如果沒有居凶,“/ ”一定能為這個(gè)URI 墊背(至少能匹配到“/ ”),也就是說“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.
前面我們說了语泽,普通location 匹配完后贸典,還會(huì)繼續(xù)匹配正則location ;但是nginx 允許你阻止這種行為踱卵,方法很簡(jiǎn)單廊驼,只需要在普通location 前加“^~ ”或“= ”。但其實(shí)還有一種“隱含”的方式來阻止正則location 的搜索惋砂,這種隱含的方式就是:當(dāng)“最大前綴”匹配恰好就是一個(gè)“嚴(yán)格精確(exact match )”匹配妒挎,照樣會(huì)停止后面的搜索。原文字面意思是:只要遇到“精確匹配exact match ”西饵,即使普通location 沒有帶“= ”或“^~ ”前綴酝掩,也一樣會(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:
- 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.
這個(gè)順序沒必要再過多解釋了。但我想用自己的話概括下上面的意思“正則 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 之后的笙各。也就是說,如果你要匹配“/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 的配置,沒什么好解釋的仑性,唯一需要說明的是location / {[configuration B]} 惶楼,原文的注釋嚴(yán)格來說是錯(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. ”大意是說:“l(fā)ocation / {} 能夠匹配所有HTTP 請(qǐng)求豹储,因?yàn)槿魏蜨TTP 請(qǐng)求都必然是以‘/ ’開始的(這半句沒有錯(cuò)誤)。但是淘这,正則location 和其他任何比‘/ ’更長(zhǎng)的普通location (location / {} 是普通location 里面最短的剥扣,因此其他任何普通location 都會(huì)比它更長(zhǎng),當(dāng)然location = / {} 和 location ^~ / {} 是一樣長(zhǎng)的)會(huì)優(yōu)先匹配(matched first )慨灭‰Γ” **原文作者說“ but regular expressions will be matched first. ”應(yīng)該只是想說正則 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.
需要提醒下:這里說“in any order ”和“… remain the same ”是因?yàn)樯厦嬷挥幸粋€(gè)正則location 筹陵。文章前面已經(jīng)說了正則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í)卻很少看見這樣的配置朦佩,那是因?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 **).
文章開始說了location 的語法中语稠,可以有“= ”宋彼,“^~ ”弄砍,“~ ”和“~* ”前綴,或者干脆沒有任何前綴输涕,還有“@ ”前綴音婶,但是后面的分析我們始終沒有談到“@ ”前綴。文章最后點(diǎn)內(nèi)容莱坎,介紹了“@”的用途:“@ ”是用來定義“Named Location ”的(你可以理解為獨(dú)立于“普通location (location using literal strings )”和“正則location (location using regular expressions )”之外的第三種類型)衣式,這種“Named Location ”不是用來處理普通的HTTP 請(qǐng)求的,它是專門用來處理“內(nèi)部重定向(internally redirected )”請(qǐng)求的檐什。注意:這里說的“內(nèi)部重定向(internally redirected )”或許說成“forward ”會(huì)好點(diǎn)碴卧,以為內(nèi)internally redirected 是不需要跟瀏覽器交互的,純粹是服務(wù)端的一個(gè)轉(zhuǎn)發(fā)行為乃正。