Nginx之location配置總結

nginx.jpeg

前言

Location指令是nginx中最關鍵的指令之一,location指令的功能是用來匹配不一樣的url請求,進而對請求作不一樣的處理和響應,這其中較難理解的是多個location的匹配順序,本文會做爲重點來解釋和說明。javascript

開始以前先明確一些約定,咱們輸入的網址叫作請求URI,nginx用請求URI與location中配置的URI作匹配。php

nginx文件結構

首先咱們先簡單瞭解Nginx的文件結構,Nginx的HTTP配置主要包括三個區塊,結構以下:css

Global: nginx 運行相關
Events: 與用戶的網絡鏈接相關
http
    http Global: 代理,緩存,日誌,以及第三方模塊的配置
    server
        server Global: 虛擬主機相關
        location: 地址定向,數據緩存,應答控制,以及第三方模塊的配置

從上面展現的nginx結構中能夠看出location屬於請求級別配置,這也是咱們最經常使用的配置。html

⚠️ 全部的全部的全部的指令,都要以 ; 結尾

配置 location 塊

location 語法

Location 塊經過指定模式來與客戶端請求的URI相匹配。
Location基本語法:前端

  • 匹配uri類型,有四種參數可選,固然也能夠不帶參數。
  • 命名location,用@來標識,相似於定義goto語句塊。
location [ = | ~ | ~* | ^~ ] /uri/ { … }
location @/name/ { … }

location匹配命令解釋

參數 解釋
location後沒有參數直接跟着URI,表示前綴匹配,表明跟請求中的URI從頭開始匹配。
= 用於標準 uri 前,要求請求字符串與其嚴格匹配,成功則當即處理,nginx中止搜索其餘匹配。
^~ 用於標準 uri 前,並要求一旦匹配到就會當即處理,再也不去匹配其餘的那些個正則 uri,通常用來匹配目錄
~ 用於正則 uri 前,表示 uri 包含正則表達式, 區分大小寫
~* # 用於正則 uri 前, 表示 uri 包含正則表達式, 不區分大小寫
@ 」@「 定義一個命名的 location,@定義的locaiton名字通常用在內部定向,例如error_page, try_files命令中。它的功能相似於編程中的goto。

location匹配順序

Nginx有兩層指令來匹配請求URI。第一個層次是server指令,它經過域名、ip和端口來作第一層級匹配,當找到匹配的server後就進入此server的location匹配。location的匹配並不徹底按照它們在配置文件中出現的順序來匹配,請求URI會按以下規則跟server裏配置的location匹配。java

  1. 尋找有沒有「=」等號參數徹底匹配的location,若是有徹底匹配的等號location則中止匹配,執行該location中的指令,不去匹配其它類型的location。
  2. 匹配全部非正則表達式URI的location(包括空,=,^~ 三種參數)。找到請求URI和location URI按前綴匹配最長的location,若是這個最長的location的參數是 ^~,則中止匹配,執行該location中的指令,不然暫存該location。
  3. 匹配正則表達式URI的location(包括~,~*兩種參數),按location在配置文件中出現的順序匹配,若是找到第一個匹配的locaiton則中止匹配,執行該location。
  4. 匹配完全部正則表達式都沒有匹配的location,則執行第二步中暫存的最長前綴匹配location。

簡單來講按這個規則 location 匹配命令的優先級從高到低依次爲(序號越小優先級越高):nginx

1. location = /a {…} #精準匹配
2. location ^~ /a {…} #前綴匹配
3. location ~ /a.* {…} #正則匹配(區分大小寫)
4. location ~* /a.* {…} #正則匹配(不區分大小寫)
5. location /a {…} #最長前綴匹配,可是優先級低於正則匹配。 /a 和 ^~ /a 會衝突,報錯
6. location / {} #任何沒有匹配成功的,都會匹配這裏處理

讓咱們用一個例子來講明上面的內容:web

# 請求:
# /
# /index.html
# /documents/document.html
# /images/1.gif
# /documents/1.jpg

location  = / {
    # 只匹配 / 的查詢.
  [ configuration A ] 
}
# 能匹配成功: / 

location / {
    # 匹配任何請求,由於全部請求都是以」/"開始
    # 可是更長字符匹配或者正則表達式匹配會優先匹配
  [ configuration B ] 
}
#能匹配成功:/index.html

location /documents/ {
    # 匹配任何以 /documents/ 開頭的地址,匹配符合之後,還要繼續往下搜索/
    # 只有後面的正則表達式沒有匹配到時,這一條纔會採用這一條/
  [ configuration C ] 
}
# 能匹配成功:/documents/document.html

location ~ /documents/ABC {
    # 匹配任何以 /documents/ 開頭的地址,匹配符合之後,還要繼續往下搜索/
    # 只有後面的正則表達式沒有匹配到時,這一條纔會採用這一條/
  [ configuration CC ] 
}

location ^~ /images/ {
    # 匹配任何以 /images/ 開頭的地址,匹配符合之後,中止往下搜索正則,採用這一條。/
  [ configuration D ] 
}
# 能成功匹配:/images/1.gif

location ~* \.(gif|jpg|jpeg)$ {
    # 匹配全部以 .gif、.jpg 或 .jpeg 結尾的請求,不區分大小寫
    # 然而,全部請求 /images/ 下的圖片會被 [ config D ]  處理,由於 ^~ 到達不了這一條正則/
    [ configuration E ] 
}
# 能成功匹配:/documents/1.jpg

location /images/ {
    # 字符匹配到 /images/,繼續往下,會發現 ^~ 存在/
  [ configuration F ] 
}

location /images/abc {
    # 最長字符匹配到 /images/abc,繼續往下,會發現 ^~ 存在/
    # F與G的放置順序是沒有關係的/
  [ configuration G ] 
}

location ~ /images/abc/ {
    # 只有去掉 [ config D ] 纔有效:先最長匹配 [ config G ] 開頭的地址,繼續往下搜索,匹配到這一條正則,採用/
    [ configuration H ] 
}

location ~* /js/.*/\.js

匹配問號後的參數

請求URI中問號後面的參數是不能在location中匹配到的,這些參數存儲在$query_string變量中,能夠用if來判斷。
例如,對於參數中帶有單引號’進行匹配而後重定向到錯誤頁面。面試

/plus/list.php?tid=19&mid=1124’
if ( $query_string ~* 「.*[;’<>].*」 ){
  return 404;
}

location URI結尾帶不帶/

這個不少解釋不太準確,我有必要多說幾句。
對於請求URI結尾是否帶有/,通常的處理邏輯是帶/表示訪問目錄,不帶/表示訪問文件,若是文件不存在也會去匹配目錄。例如訪問http://www.nginx.cn/images/和...://www.nginx.cn/images,前面的請求會匹配目錄,後面的請求會先匹配文件,文件不存再匹配目錄
對於locatioin中的URI來講,若是URI的結尾帶有/,而且location要執行的命令式是proxy_pass、fastcgi_pass、uwsgi_pass、scgi_pass、memcached_pass、grpc_pass之一。例如:正則表達式

location  /images/ {
  proxy_pass http://www.redis.com.cn
}

對於這種狀況,nginx會作特殊處理,無論images命名的文件或目錄存在不在,若是你訪問http://www.nginx.cn/images會...://www.nginx.cn/images/。
因此若是你想這兩種請求對應不一樣的處理,就要明確增長不帶/結尾的location配置。

location  /images {
  proxy_pass http://www.rabbitmq.cn
}
location  /images/ {
  proxy_pass http://www.redis.com.cn
}

命名location

帶有」@「的location是用來定義一個命名的location,這種location不參與請求匹配,通常用在內部定向。例如用在error_page, try_files命令中。它的功能相似於編程中的goto。

location /images {
  try_files $uri $uri/ @name;
}
location @name {
  …
}

實際使用建議

因此實際使用中,我的以爲至少有三個匹配規則定義,以下:

直接匹配網站根,經過域名訪問網站首頁比較頻繁,使用這個會加速處理,官網如是說。

這裏是直接轉發給後端應用服務器了,也能夠是一個靜態首頁。第一個必選規則:

location = / {
    proxy_pass http://tomcat:8080/index
}

第二個必選規則是處理靜態文件請求,這是nginx做爲http服務器的強項,有兩種配置模式,目錄匹配或後綴匹配,任選其一或搭配使用:

location ^~ /static/ {
    root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
    root /webroot/res/;
}

第三個規則就是通用規則,用來轉發動態請求到後端應用服務器,非靜態文件請求就默認是動態請求,本身根據實際把握,畢竟目前的一些框架的流行,帶.php,.jsp後綴的狀況不多了:

location / {
    proxy_pass http://tomcat:8080/
}

本文參考/引用:
Module ngx_http_core_module - nginx.org
nginx 中文文檔 - nginx location匹配規則 - nginx.cn
nginx 一文完全讀懂nginx中的location指令 - nginx.cn
nginx 這一篇就夠了 - 哆啦A夢的猜測 - 掘金
nginx 配置location總結及rewrite規則寫法 - seanlook - 思否
nginx平臺初探(100%) — Nginx開發從入門到精通

推薦閱讀:
【專題:JavaScript進階之路】
JavaScript中各類源碼實現(前端面試筆試必備)
深刻理解 ES6 Promise
前端性能優化小結(面試乾貨)
ES6 尾調用和尾遞歸


我是Cloudy,現居上海,年輕的前端攻城獅一枚,愛專研,愛技術,愛分享。
我的筆記,整理不易,感謝關注閱讀點贊收藏
文章有任何問題歡迎你們指出,也歡迎你們一塊兒交流各類前端問題!
相關文章
相關標籤/搜索