1. 程式人生 > >Nginx筆記之Rewrite規則

Nginx筆記之Rewrite規則

test 整理 區別 reg 如果 跳轉 判斷 var 我們

Nginx中Rewrite規則主要用於實現URL的重寫。通過Rewrite規則,可以實現規範的URL、根據變量來做URL轉向及選擇配置。

Rewrite規則相關命令

  • break
  • if
  • return
  • rewrite
  • set

break命令

break的作用即完成當前規則集,後續不再處理rewrite命令。

if ($slow)
{
    limit_rate 10k;
    break;
}

if命令

if條件判斷,判斷一個條件是否符合,符合就執行代碼段內的命令。Nginx內的if命令不支持嵌套,也不支持多一個條件處理(&&或||)

if命令是Rewrite規則內使用較多的一個命令,很多信息都可以作為if的條件進行判斷。大致分為以下幾種:

  1. 變量名是否為空
  2. 變量比較:=、!=
  3. 正則匹配
    1. 模糊匹配 ~*
    2. 完全匹配 ~
    3. 不匹配
      1. 不完全匹配 !~
      2. 不模糊匹配 !~*
  4. 文件是否存在 -f | !-f
  5. 目錄是否存在 -d | !-d
  6. 文件或目錄是否存在 -e | !-e
  7. 文件是否可執行 -x | !-x

例如:

if ($http_user_agent ~ MSIE)
{
    rewrite ^(.*)$ /msie/$1 break;
}
if ($http_cookie ~* "id=([^;] +)(?:;|$)")
{
    set $id $1;
}
if ($request_method = POST)
{
    return 405;
}
if (!-f $request_filename)
{
    break;
    proxy_pass http://127.0.0.1;
}
if ($slow)
{
    limit_rate 10k;
}
if ($invalid_referer)
{
    return 403;
}
if ($args ^~ post=140)
{
    rewrite ^ http://example.com/ permanent;
}

return命令

return命令用於結束規則的執行並返回狀態碼信息給客戶端。常用的可用狀態碼包括:

  • 403 Forbidden,服務器拒絕執行
  • 404 Not Found,請求的資源為找到
  • 500 Internet Server Error,服務器遇到錯誤,導致無法完成對請求的處理(常出現在服務器的程序代碼出現錯誤時)
  • 502 Bad Gateway,網關或代理無效
  • 503 Service Unabailable,服務器由於臨時進行維護或過載導致無法處理請求
  • 504 Gateway Timeout,作為網關或代理的服務器處理請求時未能及時從上遊服務器得到響應。

rewrite(核心)

作為rewrite規則內的核心命令,rewrite命令根據表達式來重定向URI,或者修改字符串。執行命令按其在配置文件內的順序。

重寫表達式子對相對路徑有效;如果想匹配主機名,需要配置if命令

rewrite語法:rewrite regex replacement flag

rewrite命令支持的flag:

  • last 完成rewrite,類似於apache內的[L]標記
  • break 本條規則匹配後終止匹配,後續規則不在匹配
  • redirect 返回狀態碼302,表示臨時性的重定向
  • permanent 返回狀態碼301,永久重定向

last和break用來實現URI重寫,瀏覽器顯示的URI地址不變,但服務器端訪問的路徑發生了變化;redirect和permanent用來實現URI跳轉,瀏覽器會顯示跳轉後的URI地址。

last會在本條rewrite規則執行後重新在所在塊內發起請求,而break則在本條規則匹配後終止匹配,因此last在某些情況下誤使用將導致死循環。一般在根location中或直接在server標簽中編寫rewrite規則,推薦使用last;在非根location中使用break。例如:

# 對於location / {...}塊而言,可以直接寫內部的代碼,不寫location
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$1.mp3 last;
return 403;

location 、download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$1.mp3 break;
    return 403;
}

如果被替換的URI中含有參數(例如/app/test.php?id=5),默認參數會被自動附加到替換串上,我們可以通過在替換串的末尾加上?來解決這一問題。

rewrite ^/user/(.*)$ /show?user=$1? last;

# 末尾不加?
# rewrite ^/test(.*)$ http://www.aaa.com/home permanent;
# 對於訪問http://www.aaa.com/test?id=5,跳轉後將訪問http://www.aaa.com/home?id=5

# 末尾加?
# rewrite ^/test(.*)$ http://www.aaa.com/home? permanent;
# 對於訪問http://www.aaa.com/test?id=5,跳轉後將訪問http://www.aaa.com/home

set命令

set命令用於定義一個變量,還可以給變量進行賦值。配合if可以實現多條件。例如

if ($host ~* ^(.*?)\.aaa\.com$)
{
    set $var_test ‘1‘;
}
if ($host ~* ^localhost)
{
    set $var_test ‘1‘;
}
if ($var_test !~ ‘1‘)
{
    rewrite ^/(.*)$ http://www.aaa.com/ redirect;
}

Nginx與Apache的Rewrite規則實例對比

一般來說,,簡單的nginx和apache的rewrite規則相差不大,只有小小修復即可實現兼容。

Apache Rewrite規則:

RewriteRule ^/(.*)$ http://www.aaa.com/$1 [L]

Nginx Rewrite規則:

rewrite ^/(.*)$ http://www.aaa.com/$1 last;

兩者的細微區別

  • URL跳轉方面
# nginx
# nginx要求給轉換後的URL添加域名:http://$host
rewrite ^/(.*)$ http://www.aaa.com/$1/ permanent;

# apache
RewriteRule ^/(.*)$ /$1/ [R=301,L]
  • 變量名稱
# apache引用變量
${HTTP_HOST}

# nginx引用變量
$host

兩者的相似命令

apache nginx
RewriteCond if
RewriteRule rewrite
[R] redirect
[P] last
[R,L] redirect
[P,L] last
[PT,L] last

本文是一篇讀書筆記,是對書內某個章節的知識整理,以防遺忘。

Nginx筆記之Rewrite規則