Nginx 重寫規則指南

HesterPLGF 8年前發布 | 13K 次閱讀 Nginx 正則表達式 Web服務器

當運維遇到要重寫情況時,往往是要程序員把重寫規則寫好后,發給你,你再到生產環境下配置。對于重寫規則說到底就是正則匹配,做運維的豈能對正則表達式不了解的?最起碼最基本的正則表達式會寫。套用一句阿里的話(某網友說是阿里說的,不清楚到底是不是出自阿里)“不懂程序的運維,不是好運維;不懂運維的開發,不是好開發。”。 正則表達式也是一門語言哈。當你學習一門語言時,必然會遇到該門語言的正則表達式這章節的。 在這里推薦一本非常好的正則表達式書,包含常用的語言的正則寫法如sed、perl、bash、awk、php、c#、java、javascript、python、ruby等等,《Regular Expressions Cookbook, 2nd Edition》,也有中文版的,大家可以到網絡上找找。

本文介紹nginx的重寫模塊,創建重寫規則向導,便于快捷正確的創建新的重寫規則,不求救于人。同時,如果想把apache轉換成nginx,重寫規則也是要改的咯。

一. rewrite模塊介紹

nginx的重寫模塊是一個簡單的正則表達式匹配與一個虛擬堆疊機結合。依賴于PCRE庫,因此需要安裝pcre。根據相關變量重定向和選擇不同的配置,從一個location跳轉到另一個location,不過這樣的循環最多可以執行10次,超過后nginx將返回500錯誤。同時,重寫模塊包含set指令,來創建新的變量并設其值,這在有些情景下非常有用的,如記錄條件標識、傳遞參數到其他location、記錄做了什么等等。

二. rewrite模塊指令

break

語法:break

默認值:none

使用字段:server, location, if

完成當前設置的重寫規則,停止執行其他的重寫規則。

if

語法:if (condition) { … }

默認值:none

使用字段:server, location

注意:盡量考慮使用try_files代替。判斷的條件可以有以下值:

  1. 一個變量的名稱:空字符傳“”或者一些“0”開始的字符串為false。

  2. 字符串比較:使用=或!=運算符

  3. 正則表達式匹配:使用~(區分大小寫)和~*(不區分大小寫),取反運算!~和!~*。

  4. 文件是否存在:使用-f和!-f操作符

  5. 目錄是否存在:使用-d和!-d操作符

  6. 文件、目錄、符號鏈接是否存在:使用-e和!-e操作符

  7. 文件是否可執行:使用-x和!-x操作符

return

語法:return code

默認值:none

使用字段:server, location, if

停止處理并為客戶端返回狀態碼。非標準的444狀態碼將關閉連接,不發送任何響應頭。可以使用的狀態碼有:204,400,402-406,408,410, 411, 413, 416與500-504。如果狀態碼附帶文字段落,該文本將被放置在響應主體。相反,如果狀態碼后面是一個URL,該URL將成為location頭補值。沒有狀態碼的URL將被視為一個302狀態碼。

rewrite

語法:rewrite regex replacement flag

默認值:none

使用字段:server, location, if

按照相關的正則表達式與字符串修改URI,指令按照在配置文件中出現的順序執行。可以在重寫指令后面添加標記。

注意:如果替換的字符串以http://開頭,請求將被重定向,并且不再執行多余的rewrite指令。

尾部的標記(flag)可以是以下的值:

  • last – 停止處理重寫模塊指令,之后搜索location與更改后的URI匹配。

  • break – 完成重寫指令。

  • redirect – 返回302臨時重定向,如果替換字段用http://開頭則被使用。

  • permanent – 返回301永久重定向。

rewrite_log

語法:rewrite_log on | off

默認值:rewrite_log off

使用字段:server, location, if

變量:無

啟用時將在error log中記錄notice級別的重寫日志。

set

語法:set variable value

默認值:none

使用字段:server, location, if

為給定的變量設置一個特定值。

uninitialized_variable_warn

語法:uninitialized_variable_warn on|off

默認值:uninitialized_variable_warn on

使用字段:http, server, location, if

控制是否記錄未初始化變量的警告信息。

三. 重寫規則組成部分

3.1 任何重寫規則的第一部分都是一個正則表達式

可以使用括號來捕獲,后續可以根據位置來將其引用,位置變量值取決于捕獲正則表達式中的順序,$1引用第一個括號中的值,$2引用第二個括號中的值,以此類推。如:

^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$

$1是兩個小寫字母組成的字符串,$2是由小寫字母和0到9的數字組成的5個字符的字符串,$3將是個文件名,$4是png、jpg、gif中的其中一個。

3.2 重寫規則的第二部分是URI

請求被改寫。該URI可能包含正則表達式中的捕獲的位置參數或這個級別下的nginx任何配置變量。如:

/data?file=$3.$4

如果這個URI不匹配nginx配置的任何location,那么將給客戶端返回301(永久重定向)或302(臨時重定向)的狀態碼來表示重定向類型。該狀態碼可以通過第三個參數來明確指定。

3.3 重寫規則的第三部分

第三部分也就是尾部的標記(flag)。 last標記將導致重寫后的URI搜索匹配nginx的其他location,最多可循環10次。如:

rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4 last;

break指令可以當做自身指令。如:

if ($ bwhog ) {

limit _ rate 300k ;

break ;

}

另一個停止重寫模塊處理指令是return, 來控制主HTTP模塊處理請求。 這意味著,nginx直接返回信息給客戶端,與error_page結合為客戶端呈現格式化的HTML頁面或激活不同的模塊來完成請求。如果狀態碼附帶文字段落,該文本將被放置在響應主體。相反,如果狀態碼后面是一個URL,該URL將成為location頭補值。沒有狀態碼的URL將被視為一個302狀態碼。如:

location = / image404 . html {

return 404 "image not found\n" ;

}

四. 實例

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 main ;

root / data / images ;

# 應用前面定義的變量。判斷首先文件在不在,不在再判斷目錄在不在,如果還不在就跳轉到最后一個url里

try_files / $ arg_file / image404 . html ;

}

location = / image404 . html {

# 圖片不存在返回特定的信息

return 404 "image not found\n" ;

}

}

五. 創建新的重新規則

在接到要創建新的重寫規則時,要弄清楚需求是什么樣的,再決定怎么做。畢竟重寫也是耗資源的有效率之分的。 下面的這些問題有些幫助的:

  1. 你的URL的模式是什么樣的?

  2. 是否有一個以上的方法來實現?

  3. 是否需要捕獲URL部分作為變量?

  4. 重定向到另一個web上可以看到我的規則?

  5. 是否要替換查詢的字符串參數?

檢查網站或應用程序布局,清楚URL模式。啰嗦一句:我一而再再而三的強調,運維不能與開發脫節,運維要參與到開發當中。如果有不止一種方法實現,創建一個永久重定向。同時,定義一個重寫規范,來使網址清潔,還可以幫助網站更容易被找到。

實例1. 要將home目錄重定向到主頁面上,目錄結構如下:

/

/ home

/ home /

/ home / index

/ home / index /

/ index

/ index . php

/ index . php /

重寫規則如下:

rewrite ^/ ( home ( / index )? | index (\. php )?) / ?$ $ scheme :

//$host/ permanent;

指定$scheme和$host變量,因為要做一個永久重定向并希望nginx使用相同的參數來構造URL。

實例2. 如果想分別記錄各個部分的URL,可以使用正則表達式來捕獲URI,然后,給變量分配指定位置變量,見上面的實例。

實例3. 當重寫規則導致內部重定向或指示客戶端調用該規則本身被定義的location時,必須采取特殊的動作來避免重寫循環。如:在server配置段定義了一條規則帶上last標志,在引用location時,必須使用break標志。

server {

rewrite ^ ( / images ) / (. * )\.( png | jpg | gif )$ $ 1 / $ 3 / $ 2. $ 3 last ;

location / images / {

rewrite ^ ( / images ) / (. * )\.( png | jpg | gif )$ $ 1 / $ 3 / $ 2. $ 3 break ;

}

}

實例4. 作為重寫規則的一部分,傳遞新的查詢字符串參數是使用重寫規則的目標之一。 如:

rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;

nginx重寫規則說起來挺簡單的,做起來就難,重點在于正則表達式,同時,還需要考慮到nginx執行順序。

 

 

 

來自:http://mp.weixin.qq.com/s?__biz=MzAwNjA3NDMyOA==&mid=2659762695&idx=2&sn=d0d2cf9c5c7e5a8dfc753d2271d9167a&chksm=806e98b0b71911a67e20025d5f9bbd1c11d58d50cc68594da9aec9f35da74a9fb2b064faec77&scene=0#wechat_redirect

 

 本文由用戶 HesterPLGF 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!