nginx中location對url匹配;
語法:location [=|~|~*|^~] /uri/ { … }
當匹配中符合條件的location,則執行內部指令;如果使用正則表達式,必須使用~*表明不區分大小寫或者~區分大小寫匹配;例如:location ~* \.(gif|jpg|jpeg)$ ;當配皮成功后,將停止往下匹配;如果沒有找到,則使用常規自字符串處理結果;
如果不是用正則表達式;可使用=嚴格匹配;
如果使用^~前綴用於一個常規字符串;表示如果路徑匹配,則不測試正則表達式;
總結:指令按下列順序被接受
1:=前綴的指令嚴格匹配這個查詢;如果找到停止往下匹配
2:掙下的常規字符串,長的在前,如果這個匹配使用^~前綴,匹配停止;
3:正則表達式,按配置文件的順序;
4:如果第三步產生匹配。則使用這個結果;停止匹配;否則使用第二部的匹配結果;
四個案例:
location = / { #只匹配/查詢 } location / { #匹配任何查詢,所有請求都是以/開頭。但是正則表達式規則和長的塊規則將被優先匹配和查詢; } location ^~ /images/ { # 匹配任何已 /images/ 開頭的任何查詢並且停止搜索。任何正則表達式將不會被測試。 } location ~* \.(gif|jpg|png)${ #匹配任何以gif、jpg、png結尾的請求。然后所有/images/目錄的請求將使用第三個 } 例子請求: / -> configuration A /documents/document.html -> configuration B /images/1.gif -> configuration C /documents/1.jpg -> configuration D
八個location案例
location = / { #精確匹配,/后面不能加任何字符串,符合此條件就直接返回數據,不再像下匹配。 if (-d $request_filename) { root /usr/local/nginx/html/; #當用戶訪問newweb的時候,則顯示此目錄的內容,除此之外訪問其他的任何目錄都不匹配。 [動作A] } location / { # 因為所有的地址都以/開頭,所以這條規則將匹配到所有請求,但是非精確匹配會采取正則和最長字符串會優先匹配,因此還會向下繼續匹配,比如當訪問/bbs的時候,還需要看下面是否更精確的匹配。 [ 動作B] } location /documents/ { # 匹配任何以 /documents/ 開頭的地址,匹配符合以后,還要繼續往下搜索 # 如果后面的正則表達式都沒有匹配到,就匹配這一條 [動作C] } location ^~ /images/ { #匹配任何以/images/ 開頭的任何請求並且停止搜索,后面任何正則表達式將不會被測試。 # 匹配任何以 /images/ 開頭的地址,匹配符合以后,停止往下搜索正則,采用這一條。 [動作D] } location ~* \.(gif|jpg|jpeg)$ { #~*為不區分大小寫 # 匹配所有以 gif,jpg或jpeg 結尾的請求 # 然而,所有請求/images/下的圖片會被動作D匹配處理,因為動作D有^~會優先匹配並終止匹配,所以到達不了這一條正則 [動作E] } location /images/ { # 字符匹配到 /images/,繼續往下,會發現 ^~ 存在,如果動作D存在,則這一條就不生效。 [動作F] } location /images/abc { #最長字符匹配到 /images/abc,繼續往下,會發現 ^~ 存在,如果D存在,則這一條就不生效。 #F與G的放置順序是沒有關系的 [動作G] } location ~ /images/abc/ { # 動作D存在,這一條不生效,如果注銷動作D,則會優先最長匹配 動作G 開頭的地址,然后向下匹配,到這一條的時候就會匹配並生效。 [ configuration H ] } 匹配優先級,順序 no優先級: (location =) > (location 完整路徑) > (location ^~ 路徑) > (location ~,~* 正則順序) > (location 部分起始路徑) > (/) 上面的匹配結果 按照上面的location寫法,以下的匹配示例成立: / -> config A 精確完全匹配,即使/index.html也匹配不了 /downloads/download.html -> config B 匹配B以后,往下沒有任何匹配,采用B /images/1.gif -> configuration D 匹配到F,往下匹配到D,停止往下 /images/abc/def -> config D 最長匹配到G,往下匹配D,停止往下 你可以看到 任何以/images/開頭的都會匹配到D並停止,FG寫在這里是沒有任何意義的,H是永遠輪不到的,這里只是為了說明匹配順序 /documents/document.html -> config C 匹配到C,往下沒有任何匹配,采用C /documents/1.jpg -> configuration E 匹配到C,往下正則匹配到E /documents/Abc.jpg -> config CC 最長匹配到C,往下正則順序匹配到CC,不會往下到E
當匹配成功后location中可以使用rewrite進行路由重寫;
首先需要了解nginx rewrite中可以使用到的全局變量;
$args :請求中get的參數,例如a=1&b=2;
$body_remote_add :二進制客戶地址
$body_byte_sent :相應時發送出去的body字節數數量,即使鏈接中斷這個數據也是精確的;
$content_length :請求頭中的Content_length字段
$content_type :請求中的Content_type字段
$document_root :當前請求在root指令中的位置;服務器中絕對路徑
$document_url :與uri相同
$host :請求主機頭字段,否則為服務器名稱;
$hostname :保存了當前請求中不包含指令的uri,例如:http://www.aaa.com/index.php?a=1中的/index.php;
$host :請求的服務器名稱;
$http_user_agent :客戶端瀏覽器的詳細信息,如果使用 chrome 和Firefox 則訪問結果是
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36 #chrome的瀏覽器信息 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 #Firefox的瀏覽器信息
$http_cookie : 客戶端cookie信息;
$limit_rate :如果nginx服務器中使用limit_rate配置了顯示網絡速率,則會顯示,如果沒有則為0
$remote_addr :客戶端的地址,每個客戶端的公網ip,
$remote_port :客戶端請求nginx服務器時隨機打開的端口,這個每個客戶端自己的端口;
$remote_user :已經經過auth basic module驗證的用戶名
$request_body_file :作反向代理是發給服務端的本地資源名稱
$request_method :請求志願的方式,get\put\delete等
$request_filename :請求的資源文件的路徑名稱
$request_url :請求參數的原始uri,不包含主機名;如"/index.php?a=1"
$squery_string :保存了url請求的指令,與$args相同
$scheme :請求協議;如http、https、ftp
$server_protacpl :保存了客戶端請求資源使用的協議的版本,如http/1.0、http/1.1
$server_addr :保存了服務器ip
$server_name :保存了服務器的主機名;該變量不一定是用戶訪問的域名,是你的server_name配的地址;
$host :保存了用戶訪問的域名
$server_port :服務器端口
$uri與$document_uri相同 :不包含指令的uri地址
如www.aaa.com/index.php?a=1&b=2中的index.php
防盜鏈:注意location生效規則,否則防盜鏈不起作用。
配置參數說明:
none
'Referer' :來源頭部為空的情況
blocked
'Referer' :來源頭部不為空,但里面的值被代理或者防火牆刪除,這些值都不以http://或者https://開頭
server_names
'Referer' :來源頭部包含當前的server_name,就是域名
arbitary string :任意字符串,定義服務器名或者可選的url前綴,主機名可以使用*開頭或者結尾,在檢測來源頭部這個過程中,來源域名中的主機端口將會被忽視;
regular expression :正則表達式,表示排除https://或者http://開頭的字符串
下面兩個案例:
location ~* \.(gif|jpg|png|bmp)$ { valid_referers none blocked *.aaa.com server_names ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; #rewrite ^/ http://www.aaa.com/1.jpg; } }
以上所有來至aaa.com和域名中包含google和baidu的站點都可以訪問到當前站點的圖片,如果來源域名不在這個列表中,那么$invalid_referer等於1,在if語句中返回一個403給用戶,這樣用戶便會看到一個403的頁面,如果使用下面的rewrite,那么盜鏈的圖片都會顯示403.jpg。如果用戶直接在瀏覽器輸入你的圖片地址,那么圖片顯示正常,因為它符合none這個規則.
location ~* \.(gif|jpg|png|swf|flv)$ { # 防盜鏈設置,對於后綴是gif、jgp等格式的生效 valid_referers none blocked a.com *.a.com; #定義允許訪問的請求鏈接 if ($invalid_referer) { return 404; } } none:在瀏覽器輸入網站域名直接訪問的請求,需要允許訪問的 blocked:有referer首部,但是referer首部被清除了,一般是防火牆改過的請求 server_name:帶服務器名稱的,一般是本機或其他服務器的請求,a.com和*.a.com是本公司的域名,要允許訪問於是要先允許本機的訪問,再禁止其他服務器的訪問
location /public/admin/images/y.jpg { #valid_referers none blocked *.aaa.com server_names *.aaa.com ; #valid_referers none blocked www.sss.com; #設置只有該域> 名可以訪問 valid_referers none blocked 111.111.111.11; #設置只有該域名可以訪> 問 if ($invalid_referer) { rewrite ^ http://baidu.com$request_uri?; return 403; rewrite ^/ http://www.aaa.com/1.jpg; } }
常用正則匹配
. : 匹配除換行符以外的任意字符 ? : 重復0次或1次 + : 重復1次或更多次 * : 重復0次或更多次 \d :匹配數字 ^ : 匹配字符串的開始 $ : 匹配字符串的介紹 {n} : 重復n次 {n,} : 重復n次或更多次 [c] : 匹配單個字符c [a-z] : 匹配a-z小寫字母的任意一個 小括號()之間匹配的內容,可以在后面通過$1來引用,$2表示的是前面第二個()里的內容。正則里面容易讓人困惑的是\轉義特殊字符。
參考if判斷語句
if ($http_user_agent ~ MSIE) { #如果客戶端是微軟的IE瀏覽器,就將請求rewrite到msie目錄下。 rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* "id=([^;]+)(?:;|$)") { # 如果cookie匹配正則,就設置變量$id等於正則引用部分 set $id $1; 設置$id等於正則第一個括號內匹配的部分 } if ($request_method = POST) { #如果提交方法為POST,則返回狀態405(Method not allowed)。return不能返回301,302 return 405; } if ($slow) { #限速,$slow可以通過 set 指令設置 limit_rate 10k; } if (!-f $request_filename){ #如果請求的文件名不存在,則反向代理到localhost 。這里的break也是停止rewrite檢查 break; proxy_pass http://127.0.0.1; } if ($args ~ post=140){ #如果query string中包含"post=140",永久重定向到example.com rewrite ^ http://example.com/ permanent; }
nginx 配置案例參考
http { # 定義image日志格式 log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status; # 開啟重寫日志 rewrite_log on; server { root /home/www; location / { # 重寫規則信息 error_log logs/rewrite.log notice; # 注意這里要用‘’單引號引起來,避免{} rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4; # 注意不能在上面這條規則后面加上“last”參數,否則下面的set指令不會執行 set $image_file $3; set $image_type $4; } location /data { # 指定針對圖片的日志格式,來分析圖片類型和大小 access_log logs/images.log mian; root /data/images; # 應用前面定義的變量。判斷首先文件在不在,不在再判斷目錄在不在,如果還不在就跳轉到最后一個url里 try_files /$arg_file /image404.html; } location = /image404.html { # 圖片不存在返回特定的信息 return 404 "image not found\n"; } }