博客 / 詳情

返回

NGINX常用指令

最近經常用到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
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.