Nginx 重寫規則指南
當運維遇到要重寫情況時,往往是要程式設計師把重寫規則寫好後,發給你,你再到生產環境下配置。對於重寫規則說到底就是正則匹配,做運維的豈能對正規表示式不瞭解的?最起碼最基本的正規表示式會寫。套用一句阿里的話(某網友說是阿里說的,不清楚到底是不是出自阿里)“不懂程式的運維,不是好運維;不懂運維的開發,不是好開發。”。 正規表示式也是一門語言哈。當你學習一門語言時,必然會遇到該門語言的正規表示式這章節的。 在這裡推薦一本非常好的正規表示式書,包含常用的語言的正則寫法如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代替。判斷的條件可以有以下值:
- 一個變數的名稱:空字元傳“”或者一些“0”開始的字串為false。
- 字串比較:使用=或!=運算子
- 正規表示式匹配:使用~(區分大小寫)和~*(不區分大小寫),取反運算!~和!~*。
- 檔案是否存在:使用-f和!-f運算子
- 目錄是否存在:使用-d和!-d運算子
- 檔案、目錄、符號連結是否存在:使用-e和!-e運算子
- 檔案是否可執行:使用-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";
}
}
五. 建立新的重新規則
在接到要建立新的重寫規則時,要弄清楚需求是什麼樣的,再決定怎麼做。畢竟重寫也是耗資源的有效率之分的。 下面的這些問題有些幫助的:
- 你的URL的模式是什麼樣的?
- 是否有一個以上的方法來實現?
- 是否需要捕獲URL部分作為變數?
- 重定向到另一個web上可以看到我的規則?
- 是否要替換查詢的字串引數?
檢查網站或應用程式佈局,清楚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執行順序。
相關文章
- nginx偽靜態規則重寫Nginx
- Nginx URL重寫規則配置詳解Nginx
- nginx配置location總結及rewrite規則寫法Nginx
- nginx location匹配規則Nginx
- Nginx 跳轉規則Nginx
- Nginx匹配規則練習Nginx
- sql改寫優化:簡單規則重組實現SQL優化
- nginx location匹配及rewrite規則Nginx
- Nginx實現URL重寫Nginx
- 重寫遵循的原則
- 規則引擎Golang指南 – Mohit KhareGolang
- nginx的location 規則匹配練習Nginx
- 4.編寫規則
- Nginx location匹配及Rewrite重寫Nginx
- nginx TP5 URL 重寫Nginx
- PbootCMS網站nginx偽靜態規則boot網站Nginx
- LINUX命令列書寫規則Linux命令列
- Makefile-3-書寫規則
- 在 apache 中重寫規則不生效的問題 [No input file specified.] 解決Apache
- 重寫遊戲規則:金融中介圈如何改變銀行業(附下載)遊戲行業
- ThinkPHP5.0 Linux Apache/Nginx重寫URL配置PHPLinuxApacheNginx
- java安全編碼指南之:Thread API呼叫規則JavathreadAPI
- 理解 Nginx 在處理請求時的匹配規則Nginx
- Oculus Quest 2如何改寫遊戲規則?遊戲
- java安全編碼指南之:執行緒安全規則Java執行緒
- 安卓應用安全指南4.5.2使用SQLite規則書安卓SQLite
- 技術專案文件書寫規範指南
- Nginx的location規則:優先順序和路徑替換Nginx
- 規則
- Nginx入門指南Nginx
- Nginx 配置二級虛擬目錄訪問 Laravel 重寫NginxLaravel
- 撰寫論文的十個簡單規則 | PLOS
- 重構複雜條件的規則設計模式 - levelup設計模式
- 安卓應用安全指南4.1.2建立/使用活動規則書安卓
- 正則匹配規則2
- url規則
- makefile規則
- ESlint規則EsLint
- [P/Invoke] 使用 `SetDllImportResolver`[^1] 改寫 `DllImport` 的庫解析規則Import