(轉載)關於一些對location認識的誤區

原文:https://www.cnblogs.com/lidabo/p/4169396.html

關於一些對location認識的誤區

一、 location 的匹配順序是「先匹配正則,再匹配普通」。html

矯正: location 的匹配順序實際上是「先匹配普通,再匹配正則」。我這麼說,你們必定會反駁我,由於按「先匹配普通,再匹配正則」解釋不了你們平時習慣的按「先匹配正則,再匹配普通」的實踐經驗。這裏我只能暫時解釋下,形成這種誤解的緣由是:正則匹配會覆蓋普通匹配(實際的規則,比這複雜,後面會詳細解釋)。nginx

 

二、 location 的執行邏輯跟 location 的編輯順序無關。web

矯正:這句話不全對,「普通 location 」的匹配規則是「最大前綴」,所以「普通 location 」的確與 location 編輯順序無關;可是「正則 location 」的匹配規則是「順序匹配,且只要匹配到第一個就中止後面的匹配」;「普通location 」與「正則 location 」之間的匹配順序是?先匹配普通 location ,再「考慮」匹配正則 location 。注意這裏的「考慮」是「可能」的意思,也就是說匹配完「普通 location 」後,有的時候須要繼續匹配「正則 location 」,有的時候則不須要繼續匹配「正則 location 」。兩種狀況下,不須要繼續匹配正則 location :( 1 )當普通 location 前面指定了「 ^~ 」,特別告訴 Nginx 本條普通 location 一旦匹配上,則不須要繼續正則匹配;( 2 )當普通location 剛好嚴格匹配上,不是最大前綴匹配,則再也不繼續匹配正則。正則表達式

總結一句話:  「正則 location 匹配讓步普通 location 的嚴格精確匹配結果;但覆蓋普通 location 的最大前綴匹配結果」express

 

官方文檔解釋

REFER:  http://wiki.nginx.org/NginxHttpCoreModule#location瀏覽器

 

locationapp

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

default: nocurl

context: serverjsp

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:

  1. 「~」 for case sensitive matching
  2. 「~*」 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:

  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.

這個順序不必再過多解釋了。但我想用本身的話歸納下上面的意思「正則 location 匹配讓步普通location 的嚴格精確匹配結果;但覆蓋普通 location 的最大前綴匹配結果」。

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 通常都會進行URLEncode ,例如「空格」會被編碼爲  ,可是Nginx 的URL 的匹配都是針對URLDecode 以後的。也就是說,若是你要匹配「/images/ /test 」,你寫location 的時候匹配目標應該是:「/images/ /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 ^~ /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 個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
  • /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 」是由於上面只有一個正則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 是不須要跟瀏覽器交互的,純粹是服務端的一個轉發行爲。

 

安裝Nginx

wget     http://nginx.org/download/nginx-1.4.6.tar.gz

tar zxvf nginx-1.1.0.tar.gz

./configure

make

make install

須要注意的是在 configure 這步遇到點小麻煩:

./configure: error: the HTTP rewrite module requires the PCRE library.

安裝 nginx 的時候, rewrite 模塊默認是須要被安裝的。可是 rewrite 模塊所依賴的 PCRE 庫須要額外安裝。

You can either disable the module by using –without-http_rewrite_module

option, or install the PCRE library into the system, or build the PCRE library

statically from the source with nginx by using –with-pcre=<path> option.

 

解決辦法: http://apps.hi.baidu.com/share/detail/34331473

先執行: yum -y install pcre-devel openssl openssl-devel  把依賴的東西安裝上。

備註: PCRE (Perl Compatible Regular Expressions )是perl語言正則表達式。 Nginx的rewrite的正則表達式採用的是Perl語法集(常識:正則表達式有不一樣的語法集,咱們常見的grep指令若是須要採用Perl語法集,須要grep -P 來指定)。

 

location 實例練習

Nginx 的語法形式是: location [=|~|~*|^~|@] /uri/ { … } ,意思是能夠以「 = 」或「 ~* 」或「 ~ 」或「 ^~ 」或「 @ 」符號爲前綴,固然也能夠沒有前綴(由於 [A] 是表示可選的 A ; A|B 表示 A 和 B 選一個),緊接着是 /uri/ ,再接着是{…} 指令塊,整個意思是對於知足這樣條件的 /uri/ 適用指令塊 {…} 的指令。

上述各類 location 可分兩大類,分別是:「普通 location 」,官方英文說法是 location using   literal strings 和「正則 location 」,英文說法是 location using regular expressions 。其中「普通 location 」是以「 = 」或「 ^~ 」爲前綴或者沒有任何前綴的 /uri/ ;「正則 location 」是以「 ~ 」或「 ~* 」爲前綴的 /uri/ 。

那麼,當咱們在一個 server 上下文編寫了多個 location 的時候, Nginx 對於一個 HTTP 請求,是如何匹配到一個 location 作處理呢?用一句話簡單歸納 Nginx 的 location 匹配規則是:「正則 location 」讓步 「普通 location」的嚴格精確匹配結果;但覆蓋 「普通 location 」的最大前綴匹配結果。理解這句話,我想經過下面的實例來講明。

#1 先普通 location ,再正則 location

周邊很多童鞋告訴我, nginx 是「先匹配正則 location 再匹配普通 location 」,其實這是一個誤區, nginx 實際上是「先匹配普通 location ,再匹配正則 location 」,可是普通 location 的匹配結果又分兩種:一種是「嚴格精確匹配」,官方英文說法是「 exact match 」;另外一種是「最大前綴匹配」,官方英文說法是「 Literal strings match the beginning portion of the query – the most specific match will be used. 」。咱們作個實驗:

 

例題 1 :假設 nginx 的配置以下

server {

       listen       9090;

       server_name  localhost;

                  location / {

           root   html;

           index  index.html index.htm;

           deny all;

       }

       location ~ \.html$ {

           allow all;

       }

}

附錄 nginx 的目錄結構是: nginx->html->index.html

上述配置的意思是: location / {… deny all;} 普通 location 以「 / 」開始的 URI 請求(注意任何 HTTP 請求都必然以「/ 」開始,因此「 / 」的意思是全部的請求都能被匹配上),都拒絕訪問; location ~\.html$ {allow all;} 正則 location以 .html 結尾的 URI 請求,都容許訪問。

 

測試結果:

[root@web108 ~]# curl http://localhost:9090/

<html>

<head><title>403 Forbidden</title></head>

<body bgcolor=」white」>

<center><h1>403 Forbidden</h1></center>

<hr><center>nginx/1.1.0</center>

</body>

</html>

[root@web108 ~]# curl http://localhost:9090/index.html

<html>

<head>

<title>Welcome to nginx!</title>

</head>

<body bgcolor=」white」 text=」black」>

<center><h1>Welcome to nginx!</h1></center>

</body>

</html>

[root@web108 ~]# curl http://localhost:9090/index_notfound.html

<html>

<head><title>404 Not Found</title></head>

<body bgcolor=」white」>

<center><h1>404 Not Found</h1></center>

<hr><center>nginx/1.1.0</center>

</body>

</html>

[root@web108 ~]#

 

測試結果以下:

URI 請求 HTTP 響應
curl http://localhost:9090/ 403 Forbidden
curl http://localhost:9090/index.html Welcome to nginx!
curl http://localhost:9090/index_notfound.html 404 Not Found

 

curl http://localhost:9090/ 的結果是「 403 Forbidden 」,說明被匹配到「 location / {..deny all;} 」了,緣由很簡單HTTP 請求 GET / 被「嚴格精確」匹配到了普通 location / {} ,則會中止搜索正則 location ;

curl http://localhost:9090/index.html 結果是「 Welcome to nginx! 」,說明沒有被「 location / {…deny all;} 」匹配,不然會 403 Forbidden ,但 /index.html 的確也是以「 / 」開頭的,只不過此時的普通 location / 的匹配結果是「最大前綴」匹配,因此 Nginx 會繼續搜索正則 location , location ~ \.html$ 表達了以 .html 結尾的都 allow all; 因而接着就訪問到了實際存在的 index.html 頁面。

curl http://localhost:9090/index_notfound.html   一樣的道理先匹配 location / {} ,但屬於「普通 location 的最大前綴匹配」,因而後面被「正則 location 」 location ~ \.html$ {} 覆蓋了,最終 allow all ; 但的確目錄下不存在index_notfound.html 頁面,因而 404 Not Found 。

 

若是此時咱們訪問 http://localhost:9090/index.txt 會是什麼結果呢?顯然是 deny all ;由於先匹配上了 location / {..deny all;} 儘管屬於「普通 location 」的最大前綴匹配結果,繼續搜索正則 location ,可是 /index.txt 不是以 .html結尾的,正則 location 失敗,最終採納普通 location 的最大前綴匹配結果,因而 deny all 了。

[root@web108 ~]# curl http://localhost:9090/index.txt

<html>

<head><title>403 Forbidden</title></head>

<body bgcolor=」white」>

<center><h1>403 Forbidden</h1></center>

<hr><center>nginx/1.1.0</center>

</body>

</html>

[root@web108 ~]#

#2 普通 location 的「隱式」嚴格匹配

例題 2 :咱們在例題 1 的基礎上增長精確配置

 

server {

       listen       9090;

       server_name  localhost;

                  location /exact/match.html {

           allow all;

       }

                  location / {

           root   html;

           index  index.html index.htm;

           deny all;

       }

       location ~ \.html$ {

           allow all;

       }

}

 

測試請求:

[root@web108 ~]# curl http://localhost:9090/exact/match.html

<html>

<head><title>404 Not Found</title></head>

<body bgcolor=」white」>

<center><h1>404 Not Found</h1></center>

<hr><center>nginx/1.1.0</center>

</body>

</html>

[root@web108 ~]#

 

結果進一步驗證了「普通 location 」的「嚴格精確」匹配會終止對正則 location 的搜索。這裏咱們小結下「普通 location」與「正則 location 」的匹配規則:先匹配普通 location ,再匹配正則 location ,可是若是普通 location 的匹配結果剛好是「嚴格精確( exact match )」的,則 nginx 再也不嘗試後面的正則 location ;若是普通 location 的匹配結果是「最大前綴」,則正則 location 的匹配覆蓋普通 location 的匹配。也就是前面說的「正則 location 讓步普通location 的嚴格精確匹配結果,但覆蓋普通 location 的最大前綴匹配結果」。

#3 普通 location 的「顯式」嚴格匹配和「 ^~ 」 前綴

上面咱們演示的普通 location 都是不加任何前綴的,其實普通 location 也能夠加前綴:「 ^~ 」和「 = 」。其中「 ^~」的意思是「非正則,不須要繼續正則匹配」,也就是一般咱們的普通 location ,還會繼續搜索正則 location (剛好嚴格精確匹配除外),可是 nginx 很人性化容許配置人員告訴 nginx 某條普通 location ,不管最大前綴匹配,仍是嚴格精確匹配都終止繼續搜索正則 location ;而「 = 」則表達的是普通 location 不容許「最大前綴」匹配結果,必須嚴格等於,嚴格精確匹配。

 

例題 3 :「 ^~ 」前綴的使用

server {

       listen       9090;

       server_name  localhost;

                  location /exact/match.html {

           allow all;

       }

                 location ^~ / {

           root   html;

           index  index.html index.htm;

           deny all;

       }

       location ~ \.html$ {

           allow all;

       }

}

 

把例題 2 中的 location / {} 修改爲 location ^~ / {} ,再看看測試結果:

URI 請求 修改前 修改後
curl http://localhost:9090/ 403 Forbidden 403 Forbidden
curl http://localhost:9090/index.html Welcome to nginx! 403 Forbidden
curl http://localhost:9090/index_notfound.html 404 Not Found 403 Forbidden
curl http://localhost:9090/exact/match.html 404 Not Found 404 Not Found

 

除了 GET /exact/match.html 是 404 Not Found ,其他都是 403 Forbidden ,緣由很簡單全部請求都是以「 / 」開頭,因此全部請求都能匹配上「 / 」普通 location ,但普通 location 的匹配原則是「最大前綴」,因此只有/exact/match.html 匹配到 location /exact/match.html {allow all;} ,其他都 location ^~ / {deny all;} 並終止正則搜索。

 

例題 4 :「 = 」前綴的使用

server {

       listen       9090;

       server_name  localhost;

                  location /exact/match.html {

           allow all;

       }

                 location = / {

           root   html;

           index  index.html index.htm;

           deny all;

       }

       location ~ \.html$ {

           allow all;

       }

}

例題 4 相對例題 2 把 location / {} 修改爲了 location = / {} ,再次測試結果:

URI 請求 修改前 修改後
curl http://localhost:9090/ 403 Forbidden 403 Forbidden
curl http://localhost:9090/index.html Welcome to nginx! Welcome to nginx!
curl http://localhost:9090/index_notfound.html 404 Not Found 404 Not Found
curl http://localhost:9090/exact/match.html 404 Not Found 404 Not Found
curl http://localhost:9090/test.jsp 403 Forbidden 404 Not Found

 

最能說明問題的測試是 GET /test.jsp ,實際上 /test.jsp 沒有匹配正則 location ( location ~\.html$ ),也沒有匹配 location = / {} ,若是按照 location / {} 的話,會「最大前綴」匹配到普通 location / {} ,結果是 deny all 。

#4 正則 location 與編輯順序

location 的指令與編輯順序無關,這句話不全對。對於普通 location 指令,匹配規則是:最大前綴匹配(與順序無關),若是剛好是嚴格精確匹配結果或者加有前綴「 ^~ 」或「 = 」(符號「 = 」只能嚴格匹配,不能前綴匹配),則中止搜索正則 location ;但對於正則 location 的匹配規則是:按編輯順序逐個匹配(與順序有關),只要匹配上,就當即中止後面的搜索。

 

配置 3.1

server {

       listen       9090;

       server_name  localhost;

 

       location ~ \.html$ {

           allow all; 

       }  

 

       location ~ ^/prefix/.*\.html$ {

           deny all;  

       }  

 

}

配置 3.2

server {

       listen       9090;

       server_name  localhost;

 

      

       location ~ ^/prefix/.*\.html$ {

           deny all;  

       }  

                 

                  location ~ \.html$ {

           allow all; 

       } 

 

}

 

測試結果:

URI 請求 配置 3.1 配置 3.2
curl http://localhost:9090/regextest.html 404 Not Found 404 Not Found
curl http://localhost:9090/prefix/regextest.html 404 Not Found 403 Forbidden

 

解釋:

Location ~ ^/prefix/.*\.html$ {deny all;} 表示正則 location 對於以 /prefix/ 開頭, .html 結尾的全部 URI 請求,都拒絕訪問;   location ~\.html${allow all;} 表示正則 location 對於以 .html 結尾的 URI 請求,都容許訪問。 實際上,prefix 的是 ~\.html$ 的子集。

在「配置 3.1 」下,兩個請求都匹配上 location ~\.html$ {allow all;} ,而且中止後面的搜索,因而都容許訪問, 404 Not Found ;在「配置 3.2 」下, /regextest.html 沒法匹配 prefix ,因而繼續搜索 ~\.html$ ,容許訪問,因而 404 Not Found ;然而 /prefix/regextest.html 匹配到 prefix ,因而 deny all , 403 Forbidden 。

 

配置 3.3

server {

       listen       9090;

       server_name  localhost;

 

       location  /prefix/ {

               deny all;  

       }  

          

       location  /prefix/mid/ {

               allow all; 

       }  

 

}

配置 3.4

server {

       listen       9090;

       server_name  localhost;

 

     

       location  /prefix/mid/ {

               allow all; 

       }  

                  location  /prefix/ {

               deny all;  

       }  

}

測試結果:

URI 請求 配置 3.1 配置 3.2
curl http://localhost:9090/prefix/t.html 403 Forbidden 403 Forbidden
curl http://localhost:9090/prefix/mid/t.html 404 Not Found 404 Not Found

 

測試結果代表:普通 location 的匹配規則是「最大前綴」匹配,並且與編輯順序無關。

 

#5 「@」 前綴 Named Location 使用

REFER:  http://wiki.nginx.org/HttpCoreModule#error_page

假設配置以下:

server {

       listen       9090;

       server_name  localhost;

 

        location  / {

           root   html;

           index  index.html index.htm;

           allow all;

       }

       #error_page 404 http://www.baidu.com # 直接這樣是不容許的

       error_page 404 = @fallback;

 

       location @fallback {

           proxy_pass http://www.baidu.com;

       }

}

 

上述配置文件的意思是:若是請求的 URI 存在,則本 nginx 返回對應的頁面;若是不存在,則把請求代理到baidu.com 上去作個彌補(注: nginx 當發現 URI 對應的頁面不存在, HTTP_StatusCode 會是 404 ,此時error_page 404 指令能捕獲它)。

 

測試一:

[root@web108 ~]# curl http://localhost:9090/nofound.html -i

HTTP/1.1 302 Found

Server: nginx/1.1.0

Date: Sat, 06 Aug 2011 08:17:21 GMT

Content-Type: text/html; charset=iso-8859-1

Location: http://localhost:9090/search/error.html

Connection: keep-alive

Cache-Control: max-age=86400

Expires: Sun, 07 Aug 2011 08:17:21 GMT

Content-Length: 222

 

<!DOCTYPE HTML PUBLIC 「-//IETF//DTD HTML 2.0//EN」>

<html><head>

<title>302 Found</title>

</head><body>

<h1>Found</h1>

<p>The document has moved <a href=」http://www.baidu.com/search/error.html」>here</a>.</p>

</body></html>

[root@web108 ~]#

 

當咱們 GET /nofound.html 發送給本 nginx , nginx 找不到對應的頁面,因而 error_page 404 = @fallback ,請求被代理到 http://www.baidu.com ,因而 nginx 給 http://www.baidu.com 發送了 GET /nofound.html ,但/nofound.html 頁面在百度也不存在,百度 302 跳轉到錯誤頁。

直接訪問 http://www.baidu.com/nofound.html 結果:

[root@web108 ~]# curl http://www.baidu.com/nofound.html -i

HTTP/1.1 302 Found

Date: Sat, 06 Aug 2011 08:20:05 GMT

Server: Apache

Location: http://www.baidu.com/search/error.html

Cache-Control: max-age=86400

Expires: Sun, 07 Aug 2011 08:20:05 GMT

Content-Length: 222

Connection: Keep-Alive

Content-Type: text/html; charset=iso-8859-1

 

<!DOCTYPE HTML PUBLIC 「-//IETF//DTD HTML 2.0//EN」>

<html><head>

<title>302 Found</title>

</head><body>

<h1>Found</h1>

<p>The document has moved <a href=」http://www.baidu.com/search/error.html」>here</a>.</p>

</body></html>

[root@web108 ~]#

 

測試二:訪問一個 nginx 不存在,但 baidu 存在的頁面

[root@web108 ~]# curl http://www.baidu.com/duty/ -i

HTTP/1.1 200 OK

Date: Sat, 06 Aug 2011 08:21:56 GMT

Server: Apache

P3P: CP=」 OTI DSP COR IVA OUR IND COM 」

P3P: CP=」 OTI DSP COR IVA OUR IND COM 」

Set-Cookie: BAIDUID=5C5D2B2FD083737A0C88CA7075A6601A:FG=1; expires=Sun, 05-Aug-12 08:21:56 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1

Set-Cookie: BAIDUID=5C5D2B2FD083737A2337F78F909CCB90:FG=1; expires=Sun, 05-Aug-12 08:21:56 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1

Last-Modified: Wed, 05 Jan 2011 06:44:53 GMT

ETag: 「d66-49913b8efe340″

Accept-Ranges: bytes

Content-Length: 3430

Cache-Control: max-age=86400

Expires: Sun, 07 Aug 2011 08:21:56 GMT

Vary: Accept-Encoding,User-Agent

Connection: Keep-Alive

Content-Type: text/html

 

<!DOCTYPE HTML PUBLIC 「-//W3C//DTD HTML 4.01 Transitional//EN」

「http://www.w3.org/TR/html4/loose.dtd」>

。。。。

</body>

</html>

顯示,的確百度這個頁面是存在的。

[root@web108 ~]# curl http://localhost:9090/duty/ -i

HTTP/1.1 200 OK

Server: nginx/1.1.0

Date: Sat, 06 Aug 2011 08:23:23 GMT

Content-Type: text/html

Connection: keep-alive

P3P: CP=」 OTI DSP COR IVA OUR IND COM 」

P3P: CP=」 OTI DSP COR IVA OUR IND COM 」

Set-Cookie: BAIDUID=8FEF0A3A2C31D277DCB4CC5F80B7F457:FG=1; expires=Sun, 05-Aug-12 08:23:23 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1

Set-Cookie: BAIDUID=8FEF0A3A2C31D277B1F87691AFFD7440:FG=1; expires=Sun, 05-Aug-12 08:23:23 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1

Last-Modified: Wed, 05 Jan 2011 06:44:53 GMT

ETag: 「d66-49913b8efe340″

Accept-Ranges: bytes

Content-Length: 3430

Cache-Control: max-age=86400

Expires: Sun, 07 Aug 2011 08:23:23 GMT

Vary: Accept-Encoding,User-Agent

 

<!DOCTYPE HTML PUBLIC 「-//W3C//DTD HTML 4.01 Transitional//EN」

「http://www.w3.org/TR/html4/loose.dtd」>

<html>

。。。

</body>

</html>

當 curl http://localhost:9090/duty/ -i 時, nginx 沒找到對應的頁面,因而 error_page = @fallback ,把請求代理到 baidu.com 。注意這裏的 error_page = @fallback 不是靠重定向實現的,而是所說的「 internally redirected (forward )」。

相關文章
相關標籤/搜索