最近經常用到nginx,所以想着系統的看一下常用的指令
HttpCore指令集
server_name
含義:設置虛擬服務器的名字,第一個名字將成為主服務器名稱;服務器名稱可以使用*代替名稱的第一部分或者最後一部分;也可以使用正則表達式進行捕獲,目前不常用
示例
server {
server_name example.com *.example.com www.example.*;
}
# 使用正則
server {
server_name ~^(www\.)?(.+)$;
location / {
root /sites/$2;
}
}
location
含義:根據URI設置配置,可以使用合法的字符串或者正則表達式
語法:location [=|~|~*|^~] /uri/ { ... }
上下文:server
| 匹配符 | 含義 |
|---|---|
| = | 精確匹配 |
| ~ | 正則,大小寫敏感 |
| ~* | 正則,大小寫不敏感 |
| ^~ | 前綴匹配 |
示例
location = /ceshi1/ {
proxy\_pass http://127.0.0.1:7001/xxxx;
# /ceshi1 -> /xxxx
# /ceshi1/a -> 404 Not Found
# /ceshi1a -> 404 Not Found
}
location ^~ /ceshi2/ {
proxy\_pass http://127.0.0.1:7001/xxxx;
# /ceshi2 -> /xxxx
# /ceshi2/a -> /xxxxa
# /ceshi2a -> 404 Not Found
}
詳細對比測試見附錄
常用變量
| 變量名 | 含義 |
|---|---|
| $arg_PARAMETER | GET請求的參數,PARAMETER為參數名 |
| $args/$query_string | GET請求的query_string,比如/test?xxxx=ceshi1&yyyy=ceshi2,則$args為xxxx=ceshi1&yyyy=ceshi2,$args_xxxx為ceshi1 |
| $content_type | 請求頭Content-Type |
| $cookie_COOKIE | 名稱為COOKIE的cookie |
| $host | 按照以下優先順序:來自請求行的主機名,來自 Host 請求頭字段的主機名,或與請求匹配的服務器名 |
| $https | 如果連接以 SSL 模式運行,則為 on,否則為空字符串 |
| $is_args | 如果請求行有參數則為 ?,否則為空字符串 |
| $http_HEADER | 獲取請求頭字段,注意要將中劃線給為下劃線,示例為$http_user_agent, $http_referer |
| $remote_addr | 客户端地址 |
| $remote_port | 客户端端口 |
| $request_method | 請求方法 |
| $request_uri | 完整的原始請求URI(帶參數) |
| $scheme | 請求模式,http或https |
| $status | 響應狀態 |
| $uri/$document_uri | 請求的url path,可能和初始不同,比如使用rewrite |
HttpUpstream指令集
該模塊用於定義可被proxy_pass等指令應用的服務器組
upstream
含義:定義一組服務器,服務器可以監聽不同端口。
示例
upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
server backup1.example.com backup;
}
server {
location / {
proxy_pass http://backend;
}
}
默認情況下,使用加權輪詢均衡算法在服務器間分配請求。在上面的示例中,每 7 個請求將按如下方式分發:5 個請求轉到 backend1.example.com,另外 2 個請求分別轉發給第二個和第三個服務器。如果在與服務器通信期間發生錯誤,請求將被傳遞到下一個服務器,依此類推,直到嘗試完所有正常運行的服務器。如果無法從這些服務器中獲得成功響應,則客户端將接收到與最後一個服務器的通信結果。
server
含義:定義服務器地址和其他參數
HttpRewrite指令集
rewrite
含義:根據正則表達式修改URL或者修改字符串,注意,重寫表達式只對相對路徑有效,如果你想匹配主機名,應該使用if語句
使用位置:server或者location或者if
語法:rewrite regex replacement flag
關於flag
| 值 | 含義 |
|---|---|
| last | 停止當前請求,並根據該次修改重新發起請求,然後走一遍這個配置文件 |
| break | 替換後繼續往下執行指令(完成rewrite指令集) |
| redirect | 臨時重定向,返回302 |
| permanent | 永久重定向,返回301 |
關於參數
如果不想讓匹配的內容的參數附在重定向的後面,則在最後加一個問號,如下
rewrite ^/users/(.*)$ /show?user=$1? last;
工程示例
rewrite . /test/index.html break; # 轉發所有的請求給index.html頁面,並完成所有的rewrite指令集
break
含義:完成所有的rewrite指令集
使用位置:server,location,if
if
含義:邏輯判斷
使用位置:server,location
語法:if(condition){}
比較符
| 符號 | 含義 |
|---|---|
| = | 相等 |
| != | 不等 |
| ~* | 正則匹配,大小寫不敏感 |
| ~ | 正則匹配,大小寫敏感 |
| !~* | 不符合,大小寫不敏感 |
| !~ | 不符合,大小寫敏感 |
| -f and !-f | 判斷文件存在或者不存在 |
| -d and !-d | 檢測一個目錄是否存在 |
| -e and !-e | 檢測是否存在一個文件,一個目錄或者一個符號鏈接 |
| -x and !-x | 檢測一個文件是否可執行 |
示例
set $xsrfToken "";
if ($http_cookie ~* "XSRF-TOKEN=(.+?)(?=;|$)"){
set $xsrfToken $1; # 設置變量xsrfToken為cookie中匹配到的值
}
set
含義:設置變量的值
使用位置(上下文):server,location,if
示例:如上
return
含義:返回一個狀態值給客户端
使用位置(上下文):server,location,if
示例:
if ($invalid_referer) { # 檢測到Referers不合法,則禁止訪問,返回403
return 403;
}
HttpProxy指令集
proxy_pass
含義:設置代理服務器的協議、地址以及映射位置的可選URL,協議可以指定http或https,可以將地址指定為域名或IP地址,以及一個可選端口號;如果域名解析為多個地址,則所有這些地址將以輪詢方式使用;可以將地址指定為upstream
使用位置 http -> server -> location
語法:proxy_pass URL
轉發時,URI的傳遞方式如下
-
如果proxy_pass指定了URI,則轉發時會將location匹配的規則部分替換為URI部分
location /name/ { proxy_pass http://127.0.0.1/remote/; # http://a.com/name/test -> http://127.0.0.1/remote/test } -
如果proxy_pass沒有指定URI,則請求URL將會以location匹配為準,示例如下
location /xxxx { proxy_pass http://127.0.0.1; # 將http://a.com/xxxx/test -> http://127.0.0.1/xxxx/test }
例外情況,無法確定怎麼替換URI
- location使用正則匹配,proxy_pass不使用URI
- 使用rewrite,將忽略proxy_pass中的URI
proxy_set_header
含義:設置請求頭內容
語法:proxy_set_header header value
使用位置:http,server,location
proxy_set_header X-XSRF-TOKEN $xsrfToken;
proxy_connect_timeout
含義:定義與代理服務器建立連接的超時時間,注意,次超時時間通常不會超過75s
proxy_connect_timeout 60;
proxy_send_timeout
含義:設置將請求傳輸到代理服務器的超時時間。超時時間僅作用於兩個連續的寫操作之間,而不是整個請求的傳輸過程。如果代理服務器在該時間內未收到任何內容,則關閉連接。
proxy_send_timeout 60;
proxy_read_timeout
含義:定義從代理服務器讀取響應的超時時間。該超時時間僅針對兩個連續的讀操作之間設置,而不是整個響應的傳輸過程。如果代理服務器在該時間內未傳輸任何內容,則關閉連接。
proxy_read_timeout 60;
HttpHeaders指令集
add_header
含義:增加響應頭內容
使用位置 http -> server -> location
語法: add_header name value;
add_header Cache-Control 'no-store'; # 設置所有內容不會被緩存
expires
含義:增加響應頭Expires字段,便於確定緩存時間
使用位置:http -> server -> location
語法:expires [time|epoch|max|off]
| 值 | 含義 |
|---|---|
| time | 數量 |
| epoch | 1 January, 1970, 00:00:01 GMT |
| max | Cache-Control值為10年,Expires為31 December 2037 23:59:59 GMT |
| off | 【默認值】不使用時間 |
expires off; #不使用過期時間
注意1:優先級 強緩存優先級 > 對比緩存優先級 ;對於強緩存優先級,pragma > Cache-Control > Expires;對於對比緩存優先級,ETag > Last-Modified
注意2:Cache-Control是http1.1的頭字段,Expires是http1.0的頭字段,建議兩者都寫
注意3:Cache-Control默認值為private,其他細節不贅述
細節參考:https://www.imooc.com/article...
HttpReferer指令集
valid_referers
含義:判斷請求頭Referers的正確性,結果會賦值給$invalid_referer
使用位置:http -> server -> location
語法:valid_referers [none|blocked|server_names]
| 值 | 含義 |
|---|---|
| none | 無Referer,一般直接刷新會是如此 |
| blocked | 有,但是被刪除,這些值不以http://或者https://開頭 |
| server_names | 寫一個匹配的路徑規則,要帶域名,會從scheme後面開始匹配,端口也會忽略,寫正則以~開頭 |
location /views {
valid_referers *.com/chart/; #判斷Referer是否匹配給出的路徑,匹配則$invalid_referer為false,否則為true
if ($invalid_referer) {
return 403;
}
}
# 如果Referer為a.com/chart/1則符合規則,如果為a.com/chart則不符合,如果沒有referer也不符合
附錄:location/proxy_pass/rewrite對比使用總結
將location和proxy_pass的所有匹配情況測試結果放在下面,對應關係為【訪問path -> 轉發成的path】
location /test1 {
proxy_pass http://127.0.0.1:7001/;
# /test1 -> /
# /test1/a -> //a
# /test1a -> /a
}
location /test2 {
proxy_pass http://127.0.0.1:7001/xxxx;
# /test2 -> /xxxx
# /test2/a -> /xxxx/a
# /test2a -> /xxxxa
}
location /test3 {
proxy_pass http://127.0.0.1:7001/xxxx/;
# /test3 -> /xxxx//
# /test3/a -> /xxxx//a
# /test3a -> /xxxx/a
}
location /test4 {
proxy_pass http://127.0.0.1:7001;
# /test4 -> /test4
# /test4/a -> /test4/a
# /test4a -> /xxxx4a
}
location /test5/ {
proxy_pass http://127.0.0.1:7001/;
# /test5 -> /
# /test5/a -> /a
# /test5a -> 404 Not Found
}
location /test6/ {
proxy_pass http://127.0.0.1:7001/xxxx;
# /test6 -> /xxxx
# /test6/a -> /xxxxa
# /test6a -> 404 Not Found
}
location /test7/ {
proxy_pass http://127.0.0.1:7001/xxxx/;
# /test7 -> /xxxx/
# /test7/a -> /xxxx/a
# /test7a -> 404 Not Found
}
location /test8/ {
proxy_pass http://127.0.0.1:7001;
# /test8 -> /test8/
# /test8/a -> /test8/a
# /test8a -> 404 Not Found
}
location /test9/ {
rewrite . /b break;
proxy_pass http://127.0.0.1:7001/xxxx;
# /test9 -> /b
# /test9/a -> /b
# /test9a -> 404 Not Found
}
location ~* /test10(.*)/ {
#proxy_pass http://127.0.0.1:7001/xxxx;
# nginx無法執行通過,會報錯,不能帶URI
}
location = /ceshi1/ {
proxy_pass http://127.0.0.1:7001/xxxx;
# /ceshi1 -> /xxxx
# /ceshi1/a -> 404 Not Found
# /ceshi1a -> 404 Not Found
}
location ^~ /ceshi2/ {
proxy_pass http://127.0.0.1:7001/xxxx;
# /ceshi2 -> /xxxx
# /ceshi2/a -> /xxxxa
# /ceshi2a -> 404 Not Found
}