天天看點

nginx配置url重寫

url重寫是指通過配置conf檔案,以讓網站的url中達到某種狀态時則定向/跳轉到某個規則,比如常見的僞靜态、301重定向、浏覽器定向等

rewrite

文法

在配置檔案的

server

塊中寫,如:

server {
    rewrite 規則 定向路徑 重寫類型;
}           

複制

  • 規則:可以是字元串或者正則來表示想比對的目标url
  • 定向路徑:表示比對到規則後要定向的路徑,如果規則裡有正則,則可以使用

    $index

    來表示正則裡的捕獲分組
  • 重寫類型:
    • last :相當于Apache裡德(L)标記,表示完成rewrite,浏覽器位址欄URL位址不變
    • break;本條規則比對完成後,終止比對,不再比對後面的規則,浏覽器位址欄URL位址不變
    • redirect:傳回302臨時重定向,浏覽器位址會顯示跳轉後的URL位址
    • permanent:傳回301永久重定向,浏覽器位址欄會顯示跳轉後的URL位址

簡單例子

server {
    # 通路 /last.html 的時候,頁面内容重寫到 /index.html 中
    rewrite /last.html /index.html last;

    # 通路 /break.html 的時候,頁面内容重寫到 /index.html 中,并停止後續的比對
    rewrite /break.html /index.html break;

    # 通路 /redirect.html 的時候,頁面直接302定向到 /index.html中
    rewrite /redirect.html /index.html redirect;

    # 通路 /permanent.html 的時候,頁面直接301定向到 /index.html中
    rewrite /permanent.html /index.html permanent;

    # 把 /html/*.html => /post/*.html ,301定向
    rewrite ^/html/(.+?).html$ /post/$1.html permanent;

    # 把 /search/key => /search.html?keyword=key
    rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}           

複制

last和break的差別

因為301和302不能簡單的隻傳回狀态碼,還必須有重定向的URL,這就是return指令無法傳回301,302的原因了。這裡 last 和 break 差別有點難以了解:

  • last一般寫在server和if中,而break一般使用在location中
  • last不終止重寫後的url比對,即新的url會再從server走一遍比對流程,而break終止重寫後的比對
  • break和last都能組織繼續執行後面的rewrite指令

location

裡一旦傳回

break

則直接生效并停止後續的比對

location

server {
    location / {
        rewrite /last/ /q.html last;
        rewrite /break/ /q.html break;
    }

    location = /q.html {
        return 400;
    }
}           

複制

  • 通路

    /last/

    時重寫到

    /q.html

    ,然後使用新的

    uri

    再比對,正好比對到

    locatoin = /q.html

    然後傳回了

    400

  • 通路

    /break

    時重寫到

    /q.html

    ,由于傳回了

    break

    ,則直接停止了

if 判斷

隻是上面的簡單重寫很多時候滿足不了需求,比如需要判斷當檔案不存在時、當路徑包含xx時等條件,則需要用到

if

文法

if (表達式) {
}           

複制

  • 當表達式隻是一個變量時,如果值為空或任何以0開頭的字元串都會當做false
  • 直接比較變量和内容時,使用=或!=
  • ~正規表達式比對,~*不區分大小寫的比對,!~區分大小寫的不比對

一些内置的條件判斷:

  • -f和!-f用來判斷是否存在檔案
  • -d和!-d用來判斷是否存在目錄
  • -e和!-e用來判斷是否存在檔案或目錄
  • -x和!-x用來判斷檔案是否可執行

内置的全局變量

$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相同。           

複制

如:

通路連結是:http://localhost:88/test1/test2/test.php 
網站路徑是:/var/www/html

$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php           

複制

例子

# 如果檔案不存在則傳回400
if (!-f $request_filename) {
    return 400;
}

# 如果host不是xuexb.com,則301到xuexb.com中
if ( $host != "xuexb.com" ){
    rewrite ^/(.*)$ https://xuexb.com/$1 permanent;
}

# 如果請求類型不是POST則傳回405
if ($request_method = POST) {
    return 405;
}

# 如果參數中有 a=1 則301到指定域名
if ($args ~ a=1) {
    rewrite ^ http://example.com/ permanent;
}           

複制

在某種場景下可結合

location

規則來使用,如:

# 通路 /test.html 時
location = /test.html {
    # 預設值為xiaowu
    set $name xiaowu;
    # 如果參數中有 name=xx 則使用該值
    if ($args ~* name=(\w+?)(&|$)) {
        set $name $1;
    }
    # 301
    rewrite ^ /$name.html permanent;
}

上面表示:

    /test.html => /xiaowu.html

    /test.html?name=ok => /ok.html?name=ok           

複制

location

文法

server

塊中使用,如:

server {
    location 表達式 {
    }
}           

複制

location表達式類型

  • 如果直接寫一個路徑,則比對該路徑下的
  • ~ 表示執行一個正則比對,區分大小寫
  • ~* 表示執行一個正則比對,不區分大小寫
  • ^~ 表示普通字元比對。使用字首比對。如果比對成功,則不再比對其他location。
  • = 進行普通字元精确比對。也就是完全比對。

優先級

  1. 等号類型(=)的優先級最高。一旦比對成功,則不再查找其他比對項。
  2. ^~類型表達式。一旦比對成功,則不再查找其他比對項。
  3. 正規表達式類型(~ ~*)的優先級次之。如果有多個location的正則能比對的話,則使用正規表達式最長的那個。
  4. 正常字元串比對類型。按字首比對。

例子 - 假位址掩飾真位址

server {
    # 用 xxoo_admin 來掩飾 admin
    location / {
        # 使用break拿一旦比對成功則忽略後續location
        rewrite /xxoo_admin /admin break;
    }
    # 通路真實位址直接報沒權限
    location /admin {
        return 403;
    }
}

           

複制