語法規則:
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_pass http://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_pass http://tomcat:8080/ }
未試驗過的其他信息:
三、ReWrite語法
last – 基本上都用這個Flag。
break – 中止Rewirte,不在繼續匹配
redirect – 返回臨時重定向的HTTP狀態302
permanent – 返回永久重定向的HTTP狀態301
last – 基本上都用這個Flag。
break – 中止Rewirte,不在繼續匹配
redirect – 返回臨時重定向的HTTP狀態302
permanent – 返回永久重定向的HTTP狀態301
注:last和break最大的不同在於
- break是終止當前location的rewrite檢測,而且不再進行location匹配 - last是終止當前location的rewrite檢測,但會繼續重試location匹配並處理區塊中的rewrite規則
1、下面是可以用來判斷的表達式:
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執行
2、下面是可以用作判斷的全局變量
1、下面是可以用來判斷的表達式:
-f和!-f用來判斷是否存在文件
-d和!-d用來判斷是否存在目錄
-e和!-e用來判斷是否存在文件或目錄
-x和!-x用來判斷文件是否可執行
2、下面是可以用作判斷的全局變量
參數 | 說明 |
$args | 這個變量等於請求行中的參數。 |
$content_length | 請求頭中的Content-length字段。 |
$content_type | 請求頭中的Content-Type字段。 |
$document_root | 當前請求在root指令中指定的值。 |
$host | 請求主機頭字段,否則為服務器名稱。 |
$http_user_agent | 客戶端agent信息 |
$http_cookie | 客戶端cookie信息 |
$limit_rate | 這個變量可以限制連接速率。 |
$request_body_file | 客戶端請求主體信息的臨時文件名。 |
$request_method | 客戶端請求的動作,通常為GET或POST。 |
$remote_addr | 客戶端的IP地址。 |
$remote_port | 客戶端的端口。 |
$remote_user | 已經經過Auth Basic Module驗證的用戶名。 |
$request_filename | 當前請求的文件路徑,由root或alias指令與URI請求生成。 |
$query_string | 與$args相同。 |
$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相同。 |
例: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語法
多目錄轉成參數
abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2
if ($host ~* (.*)\.domain\.com) { set $sub_name $ rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; }
目錄對換
/123456/xxxx -> /xxxx?id=123456
/123456/xxxx -> /xxxx?id=123456
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
例如下面設定nginx在用戶使用ie的使用重定向到/nginx-ie目錄下:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; }
目錄自動加“/”
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
禁止htaccess
location ~/\.ht { deny all; }
禁止多個目錄
location ~ ^/(cron|templates)/ { deny all; break; }
禁止以/data開頭的文件
可以禁止/data/下多級目錄下.log.txt等請求;
可以禁止/data/下多級目錄下.log.txt等請求;
location ~ ^/data { deny all; }
禁止單個目錄
不能禁止.log.txt能請求
不能禁止.log.txt能請求
location /searchword/cron/ { deny all; }
禁止單個文件
location ~ /data/sql/data.sql { deny all; }
給favicon.ico和robots.txt設置過期時間;
這里為favicon.ico為99 天,robots.txt為7天並不記錄404錯誤日志
這里為favicon.ico為99 天,robots.txt為7天並不記錄404錯誤日志
location ~(favicon.ico) { log_not_found off; expires 99d; break; } location ~(robots.txt) { log_not_found off; expires 7d; break; }
設定某個文件的過期時間
這里為600秒,並不記錄訪問日志
location ^~ /html/scripts/loadhead_1.js { access_log off; root /opt/lampp/htdocs/web; expires 600; break; }
文件反盜鏈並設置過期時間
這里的return 412 為自定義的http狀態碼,默認為403,方便找出正確的盜鏈的請求
“rewrite ^/ http://error.domain.com/error.gif;”顯示一張防盜鏈圖片
“access_log off;”不記錄訪問日志,減輕壓力
“expires 3d”所有文件3天的瀏覽器緩存
這里的return 412 為自定義的http狀態碼,默認為403,方便找出正確的盜鏈的請求
“rewrite ^/ http://error.domain.com/error.gif;”顯示一張防盜鏈圖片
“access_log off;”不記錄訪問日志,減輕壓力
“expires 3d”所有文件3天的瀏覽器緩存
location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.domain.com *.domain.net localhost 208.97.167.194; if ($invalid_referer) { rewrite ^/ http://error.domain.com/error.gif; return 412; break; } access_log off; root /opt/lampp/htdocs/web; expires 3d; break; }
只充許固定ip訪問網站,並加上密碼
root /opt/htdocs/www; allow 222.11.11.11; allow 216.5.5.5; allow 105.10.10.10; deny all; auth_basic "C1G_ADMIN"; auth_basic_user_file htpasswd;
將多級目錄下的文件轉成一個文件,增強seo效果
/job-123-456-789.html 指向/job/123/456/789.html
/job-123-456-789.html 指向/job/123/456/789.html
rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;
將根目錄下某個文件夾指向2級目錄
如/shanghaijob/ 指向 /area/shanghai/
如果你將last改成permanent,那么瀏覽器地址欄顯是 /location/shanghai/
如/shanghaijob/ 指向 /area/shanghai/
如果你將last改成permanent,那么瀏覽器地址欄顯是 /location/shanghai/
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
上面例子有個問題是訪問/shanghai 時將不會匹配
rewrite ^/([0-9a-z]+)job$ /area/$1/ last; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
這樣/shanghai 也可以訪問了,但頁面中的相對鏈接無法使用,
如./list_1.html真實地址是/area /shanghia/list_1.html會變成/list_1.html,導至無法訪問。
如./list_1.html真實地址是/area /shanghia/list_1.html會變成/list_1.html,導至無法訪問。
那我加上自動跳轉也是不行咯
(-d $request_filename)它有個條件是必需為真實目錄,而我的rewrite不是的,所以沒有效果
(-d $request_filename)它有個條件是必需為真實目錄,而我的rewrite不是的,所以沒有效果
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
知道原因后就好辦了,讓我手動跳轉吧
rewrite ^/([0-9a-z]+)job$ /$1job/ permanent; rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
文件和目錄不存在的時候重定向:
if (!-e $request_filename) { proxy_pass http://127.0.0.1; }
域名跳轉
server { listen 80; server_name jump.domain.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/ http://www.domain.com/; access_log off; }
多域名轉向
server_name www.domain.com www.domain.net; index index.html index.htm index.php; root /opt/lampp/htdocs; if ($host ~ "domain\.net") { rewrite ^(.*) http://www.domain.com$1 permanent; }
三級域名跳轉
if ($http_host ~* "^(.*)\.i\.domain\.com$") { rewrite ^(.*) http://top.domain.com$1; break; }
域名鏡像
server { listen 80; server_name mirror.c1gstudio.com; index index.html index.htm index.php; root /opt/lampp/htdocs/www; rewrite ^/(.*) http://www.c1gstudio.com/$1 last; access_log off; }