本文提供一些常用的rewrite重寫規則,用來美化網頁的鏈接。規則里面的$1$2你不知道是怎么來的話,只要記住,第一個()里面的是$1,第二個()里面的是$2.
請求的URL是給人看的,重寫后的URL是給電腦看的。
執行搜索
這個規則的目的是為了執行搜索,搜索URL中包含的關鍵字。
請求的URL //hqidi.com/search/some-search-keywords
重寫后URL //hqidi.com/search.php?p=some-search-keywords
重寫規則 rewrite ^/search/(.*)$ /search.php?p=$1?;
用戶個人資料頁面
大多數運行訪問者注冊的動態網站都提供一個可以查看個人資料的頁面,這個頁面的URL包含用戶的UID和用戶名
請求的URL //hqidi.com/user/47/dige
重寫后URL //hqidi.com/user.php?id=47&name=dige
重寫規則 rewrite ^/user/([0-9]+)/(.+)$ /user.php?id=$1&name=$2?;
多個參數
有些網站對字符串參數使用不同的語法,例如 通過斜線“/”來分隔非命名參數
請求的URL //hqidi.com/index.php/param1/param2/param3
重寫后URL //hqidi.com/index.php?p1=param1&p2=param2&p3=param3
重寫規則 rewrite ^/index.php/(.*)/(.*)/(.*)$ /index.php?p1=$1&p2=$2&p3=$3?;
類似百科的格式
這種格式特點,一個前綴目錄,后跟文章名稱
請求的URL //hqidi.com/wiki/some-keywords
重寫后URL //hqidi.com/wiki/index.php?title=some-keywords
重寫規則 rewrite ^/wiki/(.*)$ /wiki/index.php?title=$1?;
論壇
論壇一般用到兩個參數,一個話題標識(topic)一個出發點(starting post)
請求的URL //hqidi.com/topic-1234-50-some-keywords.html
重寫后URL //hqidi.com/viewtopic.php?topic=1234&start=50
重寫規則 rewrite ^/topic-([0-9]+)-([0-9]+)-(.*)\.html$ viewtopic.php?topic=$1&start=$2?;
新網站的文章
這種URL結構的特點,由一個文章標識符,后跟一個斜線,和一個關鍵字列表組成。
請求的URL //hqidi.com/88/future
重寫后URL //hqidi.com/atricle.php?id=88
重寫規則 rewrite ^/([0-9]+)/.*$ /aticle.php?id=$1?;
最后一個問號
若被替換的URI中含有參數(類似/app/test.php?id=5之類的URI),默認情況下參數會被自動附加到替換串上,可以通過在替換串的末尾加上?標記來解決這一問題。
rewrite ^/users/(.*)$ /show?user=$1? last;
比較一個加上?標記和不加?標記的URL跳轉區別:
rewrite ^/test(.*)$ //hqidi.com/home premanent;
訪問//hqidi.com/test?id=5 經過301跳轉后的URL地址為 //hqidi.com/home?id=5
rewrite ^/test(.*)$ //hqidi.com/home? premanent;
訪問//hqidi.com/test?id=5 經過301跳轉后的URL地址為 //hqidi.com/home
Nginx的rewrite功能需要PCRE軟件的支持,即通過perl兼容正則表達式語句進行規則匹配的。默認參數編譯nginx就會支持rewrite的模塊,但是也必須要PCRE的支持
rewrite是實現URL重寫的關鍵指令,根據regex(正則表達式)部分內容,重定向到replacement,結尾是flag標記。
nginx rewrite指令執行順序
1.執行server塊的rewrite指令(這里的塊指的是server關鍵字后{}包圍的區域,其它xx塊類似)
2.執行location匹配
3.執行選定的location中的rewrite指令
如果其中某步URI被重寫,則重新循環執行1-3,直到找到真實存在的文件。
如果循環超過10次,則返回500 Internal Server Error錯誤。
flag標志位
rewrite的語法很簡單,如:
rewrite regex URL [flag];
rewrite是關鍵字,regex是正則表達式,URL是要替代的內容,[flag]是標記位的意思,它有以下幾種值:
- last: 相當于Apache的[L]標記,表示完成rewrite
- break: 停止執行當前虛擬主機的后續rewrite指令集
- redirect: 返回302臨時重定向,地址欄會顯示跳轉后的地址
- permanent: 返回301永久重定向,地址欄會顯示跳轉后的地址
因為301和302不能簡單的只返回狀態碼,還必須有重定向的URL,這就是return指令無法返回301,302的原因了。這里 last 和 break 區別有點難以理解:
- last一般寫在server和if中,而break一般使用在location中
- last不終止重寫后的url匹配,即新的url會再從server走一遍匹配流程,而break終止重寫后的匹配
- break和last都能組織繼續執行后面的rewrite指令
來看一個簡單實例:
rewrite ^/listings/(.*)$ /listing.html?listing=$1 last;
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;
第一條重寫規則中,我們可以使用友好的URL:http://mysite.com/listings/123代替http://mysite.com/listing.html?listing=123,就相當于我們在瀏覽器的地址欄中輸入http://mysite.com/listings/123后,實際訪問的URL資源是http://mysite.com/listing.html?listing=123。
第二條規則中,對形如http://mysite.com/images/bla_500x400.jpg的文件請求,重寫到http://mysite.com/resizer/bla.jpg?width=500&height=400地址,并會繼續嘗試匹配location。
if指令與全局變量
if指令語法為if(condition){...},對給定的條件condition進行判斷。如果為真,大括號內的rewrite指令將被執行。
來看代碼規則:
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite請求到/msid/目錄下
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} //如果cookie匹配正則,設置變量$id等于正則引用部分
if ($request_method = POST) {
return 405;
} //如果提交方法為POST,則返回狀態405(Method not allowed)。return不能返回301,302
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通過 set 指令設置
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果請求的文件名不存在,則反向代理到localhost 。這里的break也是停止rewrite檢查
if ($args ~ post=140){
rewrite ^ http://mysite.com/ permanent;
} //如果query string中包含"post=140",永久重定向到mysite.com
if指令中,可以使用全局變量,這些變量有:
- $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相同。
使用return跳轉
我們有時需要在Nginx上使用rewrite做301地址跳轉,比如以下規則:
rewrite ^ $scheme://www.mysite.com$request_uri permanent;
當訪問任意url都會301永久定向到www.mysite.com的url上。這個寫法沒錯,但是因為使用了rewrite的正則匹配,會損耗一部分資源,nginx官網不推薦這樣寫。我們可以使用return同樣可以實現301跳轉,簡單實用,看實例:
301永久定向到新域名
server {
listen 80;
listen 443 ssl;
server_name www.old-name.com old-name.com;
return 301 $scheme://www.new-name.com;
}
以上代碼實現了老域名301跳轉到新域名上,假如網站要更換新域名的話使用此方法做301跳轉。
不帶www的域名301跳轉到帶www的域名
server {
listen 80;
listen 443 ssl;
server_name mysite.com;
return 301 $scheme://www.mysite.com$request_uri;
}
http站點301跳轉到https站點
server {
listen 80;
server_name www.mysite.com;
return 301 https://www.mysite.com$request_uri;
}
以上就是有關Nginx的rewrite重寫與重定向的介紹,覺得有用就請練習多遍,收藏好此文不迷路。也希望大家多多支持腳本之家。