Nginx教程(四) Location配置與ReWrite語法
1 Location語法規則
1.1 Location規則
語法規則: location [=|~|~*|^~] /uri/ {… }
首先匹配 =,其次匹配^~,其次是按文件中順序的正則匹配,最后是交給 /通用匹配。當有匹配成功時候,停止匹配,按當前匹配規則處理請求。
符號 |
含義 |
= |
= 開頭表示精確匹配 |
^~ |
^~開頭表示uri以某個常規字符串開頭,理解為匹配 url路徑即可。nginx不對url做編碼,因此請求為/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意是空格) |
~ |
~ 開頭表示區分大小寫的正則匹配 |
~* |
~* 開頭表示不區分大小寫的正則匹配 |
!~和!~* |
!~和!~*分別為區分大小寫不匹配及不區分大小寫不匹配的正則 |
/ |
用戶所使用的代理(一般為瀏覽器) |
$http_x_forwarded_for |
可以記錄客戶端IP,通過代理服務器來記錄客戶端的ip地址 |
$http_referer |
可以記錄用戶是從哪個鏈接訪問過來的 |
匹配規則示例:
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
}
那么產生的效果如下:
1. 訪問根目錄/,比如http://localhost/將匹配規則A
2. 訪問 http://localhost/login 將匹配規則B,http://localhost/register則匹配規則H
3. 訪問 http://localhost/static/a.html 將匹配規則C
4. 訪問 http://localhost/a.gif,http://localhost/b.jpg 將匹配規則D和規則E,但是規則D順序優先,規則E不起作用,而http://localhost/static/c.png則優先匹配到規則C
5. 訪問 http://localhost/a.PNG 則匹配規則E,而不會匹配規則D,因為規則E不區分大小寫。
6. 訪問 http://localhost/a.xhtml 不會匹配規則F和規則G,http://localhost/a.XHTML不會匹配規則G,因為不區分大小寫。規則F,規則G屬於排除法,符合匹配規則但是不會匹配到,所以想想看實際應用中哪里會用到。
7. 訪問 http://localhost/category/id/1111 則最終匹配到規則H,因為以上規則都不匹配,這個時候應該是nginx轉發請求給后端應用服務器,比如FastCGI(PHP),tomcat(jsp),nginx作為方向代理服務器存在。
1.2 實際常用規則
#直接匹配網站根,通過域名訪問網站首頁比較頻繁,使用這個會加速處理。
#這里是直接轉發給后端應用服務器了,也可以是一個靜態首頁
# 第一個必選規則
location = / {
proxy_passhttp://tomcat:8080/index
}
# 第二個必選規則是處理靜態文件請求,這是nginx作為http服務器的強項
# 有兩種配置模式,目錄匹配或后綴匹配,任選其一或搭配使用
location ^~ /static/ {
# 請求/static/a.txt 將被映射到實際目錄文件:/webroot/res/static/a.txt
root /webroot/res/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)${
root /webroot/res/;
}
第三個規則就是通用規則,用來轉發動態請求到后端應用服務器
#非靜態文件請求就默認是動態請求,自己根據實際把握
#畢竟目前的一些框架的流行,帶.php,.jsp后綴的情況很少了
location / {
proxy_pass http://tomcat:8080/
}
1.3 Location解析過程
總結:
1、 先判斷精准命中,如果命中,立即返回結果並結束解析過程。
2、 判斷普通命中,如果有多個命中,“記錄”下來“最長”的命中結果(記錄但不結束,最長的為准)。
3、 繼續判斷正則表達式的解析結果,按配置里的正則表達式順序為准,由上至下開始匹配,一旦匹配成功1個,立即返回結果,並結束解析過程。
4、 普通命中順序無所謂,是因為按命中的長短來確定。正則命中,順序有所謂,因為是從前入往后命中的。
2 ReWrite語法
Nginx提供的全局變量或自己設置的變量,結合正則表達式和標志位實現url重寫以及重定向。
rewrite只能放在server{},location{},if{}中,
並且只能對域名后邊的除去傳遞的參數外的字符串起作用。
Rewrite主要的功能就是實現URL的重寫,Nginx的Rewrite規則采用Pcre,perl兼容正則表達式的語法規則匹配,如果需要Nginx的Rewrite功能,在編譯Nginx之前,需要編譯安裝PCRE庫。
通過Rewrite規則,可以實現規范的URL、根據變量來做URL轉向及選擇配置。
2.1 ReWrite相關指令
指令 |
默認值 |
使用范圍 |
作用 |
break |
none |
if,server,location |
完成當前的規則集,不再處理rewrite指令,需要和last加以區分 |
if ( condition ) { ... } |
none |
server,location |
用於檢測一個條件是否符合,符合則執行大括號內的語句。不支持嵌套,不支持多個條件&&或||處理 |
return |
none |
server,if,location |
用於結束規則的執行和返回狀態碼給客戶端。狀態碼的值可以是:204,400,402~406,408,410,411,413,416以及500~504,另外非標准狀態碼444,表示以不發送任何的Header頭來結束連接。 |
rewrite regex replacement flag |
|
server,location,if |
該指令根據表達式來重定向URI,或者修改字符串。指令根據配置文件中的順序來執行。注意重寫表達式只對相對路徑有效。 |
uninitialized_variable_warn on|off |
on |
http,server,location,if |
該指令用於開啟和關閉未初始化變量的警告信息,默認值為開啟。 |
set variable value |
none |
|
該指令用於定義一個變量,並且給變量進行賦值。變量的值可以是文本、一個變量或者變量和文本的聯合,文本需要用引號引起來。 |
2.2 Rewrite全局變量
rewrite全局變量表
變量 |
含義 |
$args |
這個變量等於請求行中的參數,同$query_string |
$content length |
請求頭中的Content-length字段。 |
$content_type |
請求頭中的Content-Type字段。 |
$document_root |
當前請求在root指令中指定的值。 |
$host |
請求主機頭字段,否則為服務器名稱。 |
$http_user_agent |
客戶端agent信息 |
$http_cookie |
客戶端cookie信息 |
$limit_rate |
這個變量可以限制連接速率。 |
$request_method |
客戶端請求的動作,通常為GET或POST。 |
$remote_addr |
客戶端的IP地址。 |
$remote_port |
客戶端的端口。 |
$remote_user |
已經經過Auth Basic Module驗證的用戶名。 |
$request_filename |
當前請求的文件路徑,由root或alias指令與URI請求生成。 |
$scheme |
HTTP方法(如http,https)。 |
$server_protocol |
請求使用的協議,通常是HTTP/1.0或HTTP/1.1。 |
$server_addr |
服務器地址,在完成一次系統調用后可以確定這個值。 |
$server_name |
服務器名稱。 |
$server_port |
請求到達服務器的端口號。 |
$request_uri |
包含請求參數的原始URI,不包含主機名,如”/foo/bar.php?arg=baz”。 |
$uri |
不帶請求參數的當前URI,$uri不包含主機名,如”/foo/bar.html”。 |
$document_uri |
與$uri相同。 |
2.3 Rewrite語法規則
操作符 |
含義 |
= ,!= |
比較的一個變量和字符串。 |
~, ~* |
與正則表達式匹配的變量,如果這個正則表達式中包含},;則整個表達式需要用"或'包圍。 |
-f,!-f |
檢查一個文件是否存在。 |
-d, !-d |
檢查一個目錄是否存在。 |
-e,!-e |
檢查一個文件、目錄、符號鏈接是否存在。 |
-x, !-x |
檢查一個文件是否可執行。 |
2.4 if指令
if 語法格式
if 空格 (條件) {
重寫模式
}
# 限制瀏覽器訪問
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
2.5 return指令
# 限制IP訪問
if ($remote_addr = 192.168.197.142) {
return 403;
}
1.首先從日志查出ip
修改conf配置文件
重啟配置文件訪問發現
2.6 rewrite指令
#判斷目錄是否存在
#服務器內部的rewrite和302跳轉不一樣.跳轉的話URL都變了,變成重新http請求index.html,而內部rewrite,上下文沒變。
if (!-e $document_root$fastcgi_script_name) {
rewrite ^.*$ /index.html break;
}
2.7 set指令
# set指令是設置變量用的,可以用來達到多條件判斷時作標志用
#判斷IE並重寫,且不用break;我們用set變量來達到目的
if ($http_user_agent ~* msie) {
set $isie 1;
}
if ($fastcgi_script_name = ie.html) {
set $isie 0;
}
if ($isie 1) {
rewrite ^.*$ ie.html;
}
常用例子
(1)表示訪問路徑有a,b,c,d都跳轉到//127.0.0.1:8080$Request_uri
location ~^/(a|b|c|d){
proxy_pass http://127.0.0.1:8080$Request_uri;
client_max_body_size 10240k;
client_body_buffer_size 128k;
}