nginx location


語法規則: location [=|~|~*|^~] /uri/ { … }
= 開頭表示精確匹配
^~ 開頭表示uri以某個常規字符串開頭,理解爲匹配 url路徑即可。nginx不對url做編碼,因此請求爲/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意是空格)。
~ 開頭表示區分大小寫的正則匹配
~* 開頭表示不區分大小寫的正則匹配
!~和!~*分別爲區分大小寫不匹配及不區分大小寫不匹配 的正則
/ 通用匹配,任何請求都會匹配到。
多個location配置的情況下匹配順序爲(參考資料而來,還未實際驗證,試試就知道了,不必拘泥,僅供參考):
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最後是交給 / 通用匹配。當有匹配成功時候,停止匹配,按當前匹配規則處理請求。
例子,有如下匹配規則:
location = / {
  #規則A
}
location = /login {
  #規則B
}
location ^~ /static/ {
  #規則C
}
location ~ \.(gif|jpg|png|js|css)$ {
  #規則D
}
location ~* \.png$ {
  #規則E
}
location !~ \.xhtml$ {
  #規則F
}
location !~* \.xhtml$ {
  #規則G
}
location / {
  #規則H
}
那麼產生的效果如下:
訪問根目錄/, 比如http://localhost/將匹配規則A
訪問 http://localhost/login將匹配規則B,http://localhost/register則匹配規則H
訪問 http://localhost/static/a.html將匹配規則C
訪問 http://localhost/a.gif,http://localhost/b.jpg將匹配規則D和規則E,但是規則D順序優先,規則E不起作用,而 http://localhost/static/c.png則優先匹配到規則C
訪問 http://localhost/a.PNG則匹配規則E,而不會匹配規則D,因爲規則E不區分大小寫。
訪問 http://localhost/a.xhtml不會匹配規則F和規則G,http://localhost/a.XHTML不會匹配規則G,因爲不區分大小寫。規則F,規則G屬於排除法,符合匹配規則但是不會匹配到,所以想想看實際應用中哪裏會用到。
訪問 http://localhost/category/id/1111則最終匹配到規則H,因爲以上規則都不匹配,這個時候應該是nginx轉發請求給後端應用服務器,比如FastCGI(php),tomcat(jsp),nginx作爲方向代理服務器存在。


所以實際使用中,個人覺得至少有三個匹配規則定義,如下:
#直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。
#這裏是直接轉發給後端應用服務器了,也可以是一個靜態首頁
# 第一個必選規則
location = / {
   proxy_passhttp://tomcat:8080/index
}
# 第二個必選規則是處理靜態文件請求,這是nginx作爲http服務器的強項
# 有兩種配置模式,目錄匹配或後綴匹配,任選其一或搭配使用
location ^~ /static/ {
   root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
   root /webroot/res/;
}
#第三個規則就是通用規則,用來轉發動態請求到後端應用服務器
#非靜態文件請求就默認是動態請求,自己根據實際把握
#畢竟目前的一些框架的流行,帶.php,.jsp後綴的情況很少了
location / {
   proxy_passhttp://tomcat:8080/
}

三、ReWrite語法
last – 基本上都用這個Flag。
break – 中止Rewirte,不在繼續匹配
redirect – 返回臨時重定向的HTTP狀態302
permanent – 返回永久重定向的HTTP狀態301
1、下面是可以用來判斷的表達式:
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執行
2、下面是可以用作判斷的全局變量
例:http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:D:\nginx/html
$request_filename:D:\nginx/html/test1/test2/test.php
四、Redirect語法
server {
listen 80;
server_name start.igrow.cn;
index index.html index.php;
root html;
if ($http_host !~ “^star\.igrow\.cn$&quot {
rewrite ^(.*) http://star.igrow.cn$1 redirect;
}
}
五、防盜鏈
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
六、根據文件類型設置過期時間
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}
七、禁止訪問某個目錄
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}
一些可用的全局變量:
$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri


 

在實際配置中,有的地方用last並不能工作,換成break就可以,其中的原理是對於根目錄的理解有所區別,按我的測試結果大致是這樣的。

#location / {
#proxy_pass http://test;
#alias /home/html/;
#root /home/html;
#rewrite "^/a/(.*)/.html$" /1.html last;
#}

在#location / { 配置裏:

1、使用root指定源:使用last和break都可以

2、使用proxy_pass指定源:使用last和break都可以

3、使用alias指定源:必須使用last

在location /a/或使用正則的location ~ ^/a/裏:

1、使用root指定源:使用last和break都可以

2、使用proxy_pass指定源:使用break和last結果有所區別

3、使用alias指定源:必須使用last

其中區別主要在proxy_pass這個標籤上,再看看幾個測試結果:

location / {
root /home/html;
}

location /a/ {
proxy_pass http://test;
rewrite "^/a/(.*)/.html$" /1.html last;
}

在這段配置裏,使用last訪問是可以訪問到東西的,不過,它出來的結果是:/home/html/1.html;可我需要的是http://test/1.html?使用break就可以了。

location / {
root /home/html;
}

location /a/ {
proxy_pass http://test;
rewrite "^/a/(.*)/.html$" /a/1.html last;
}

在這段配置裏,返回錯誤,因爲last會重新發起請求匹配,所以造成了一個死循環,使用break就可以訪問到http://test/a/1.html。

所 以,使用last會對server標籤重新發起請求,而break就直接使用當前的location中的數據源來訪問,要視情況加以使用。一般在非根的 location中配置rewrite,都是用的break;而根的location使用last比較好,因爲如果配置了fastcgi或代理訪問jsp 文件的話,在根location下用break是訪問不到。測試到rewrite有問題的時候,也不妨把這兩者換換試試。

至於使用alias時爲什麼必須用last,估計是nginx本身就限定了的,怎麼嘗試break都不能成功。


正則表達式:

昨天碰到的問題,在BBs問了得出的答應如下./(.+?)b/is  是非貪婪模式 匹配ab /(.*)b/is 是貪婪模式 匹配abb,

那麼我們來看看基本的符號說明:

*                                0次、1次或多次匹配其前的原子
+                                1次或多次匹配其前的原子
?                                0次或1次匹配其前的原子
.                                匹配除換行之外的任何一個字符

再看看簡單的例子:

你測試.+?和.*當然看不出區別了
測試這個字符串看看
'aaa<div style="font-color:red;">123456</div>bbb'
<.+?>會匹配<div style="font-color:red;">和</div>
<.*>會匹配<div style="font-color:red;">123456</div>

最後看看高手怎麼說的.

(.+)默認這是貪婪匹配
貪婪是先看整個字符串是否匹配, 如果不匹配,它會去掉字符串的最後一個字符, 並再次嘗式, 如果還不匹配, 那麼再去掉當前最後一個, 直到發現匹配或不剩任何字符.
過程大概這樣:
$str='abcdabceba'
/.+b/  // 匹配一個或多個任意字符後面跟一個字母 b

第一次(先看整個字符串是否是一個匹配) abcdabceba 不匹配,然後去掉最後一個字符 a
第二次(去掉最後一個字符後再匹配) abcdabceb  正確退出

惰性是從左側第一個字符開始向右匹配, 先看第一個字符是不是一個匹配, 如果不匹配就加入下一個字符再嘗式匹配, 直到發現匹配...
過程大概這樣
$str='abcdabceba'
/.+?b/ // 同樣匹配一個或多個任意字符後面跟一個字母 b

第一次(讀入左側第一個字符) a 不匹配加一個再式
第二次 ab  匹配記錄下來,繼續(如果匹配所有的話,比如 preg_match_all, 或preg_replace, 不是所有到這兒就停了
第三次 c
...
cdab  匹配記錄下來,繼續
...
ceb  匹配記錄下來,繼續

a 到最後了沒有了退出


簡單例子:
<?php
//這裏因爲沒有用all, .+?只匹配一次

        
$str='abcdabceba';
        
preg_match('/.+b/', $str, $s);
        echo
$s[0]; // abcdabceb
        
        
echo"   ";
        
preg_Match('/.+?b/', $str, $s);
        echo
$s[0]; // ab
        
        
echo"   ";
        
preg_Match('/.+b/U', $str, $s); //等同於 /.+?b/
        
echo $s[0]; //ab
?>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章