nginx之location匹配規則


url匹配規則

location [=|~|~*|^~|@] /uri/ {
  ...
} 

 

  • = : 表示精確匹配后面的url
  • ~ : 表示正則匹配,但是區分大小寫
  • ~* : 正則匹配,不區分大小寫
  • ^~ : 表示普通字符匹配,如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
  • @ : "@" 定義一個命名的 location,使用在內部定向時,例如 error_page

上述匹配規則的優先匹配順序:

  1. = 前綴的指令嚴格匹配這個查詢。如果找到,停止搜索;
  2. 所有剩下的常規字符串,最長的匹配。如果這個匹配使用 ^~ 前綴,搜索停止;
  3. 正則表達式,在配置文件中定義的順序;
  4. 如果第 3 條規則產生匹配的話,結果被使用。否則,使用第 2 條規則的結果。

目標地址處理規則

匹配到uri后,接下來要代理到目標服務地址。

upstream api_server {
  server 10.0.101.62:8081;
  server 10.0.101.61:8082;
}

location / {
        rewrite ^(.*)$ http://10.0.101.62:8000/my-module$1 break;
}

location ^~ /my-module/ {
    root   /data/my-module/dist;
    rewrite ^/my-module/(.*)$  /$1 break;
    index  index.html index.htm;
}

location /my-module/api {
    proxy_pass  http://api_server;
    proxy_set_header Host $host;
    proxy_set_header  X-Real-IP        $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header  your-custome-header    "myHeader";
    proxy_set_header X-NginX-Proxy true;
}

 

上述配置,默認訪問/會重定向到/my-module, 然后直接返回/data/my-module/dist下的html等靜態文件。

訪問/my-module/api則會代理到我們api服務器地址,是一個默認的round-robin負載均衡配置。

下面是訪問localhost的日志, 訪問首頁一共進行了2次重定向。

Request URL: http://10.0.101.62:8000/
Request Method: GET
Status Code: 302 Moved Temporarily
Location: http://10.0.101.62:8000/flash/

Request URL: http://10.0.101.62:8000/flash/
Request Method: GET
Status Code: 302 Moved Temporarily
Location: http://10.0.101.62:8000/flash/index.html

Request URL: http://10.0.101.62:8000/flash/index.html
Request Method: GET
Status Code: 304 Not Modified

 

alias與root的區別

root 實際訪問文件路徑會拼接URL中的路徑
alias 實際訪問文件路徑不會拼接URL中的路徑

示例如下:

location ^~ /sta/ {  
   alias /usr/local/nginx/html/static/;  
}

 

請求:http://test.com/sta/sta1.html
實際訪問:/usr/local/nginx/html/static/sta1.html 文件

location ^~ /tea/ {  
   root /usr/local/nginx/html/;  
}

 

請求:http://test.com/tea/tea1.html
實際訪問:/usr/local/nginx/html/tea/tea1.html 文件

顯然,第二次重定向是不需要的,本意是訪問/flash/的時候,直接訪問對應目錄下的html靜態文件。 但因為root拼接flash導致找不到對應文件,要重寫url,去掉flash這個模塊前綴,使用了rewrite, 而rewrite會返回302重定向。

接下來,我們修改rootalias

 location ^~ /flash/ {
    alias   /data/flash/dist/;
    #rewrite ^/flash/(.*)$  /$1 break;
    index  index.html index.htm;
}

 

直接重定向1次后返回html

Request URL: http://10.0.101.62:8000/
Request Method: GET
Status Code: 302 Moved Temporarily

Request URL: http://10.0.101.62:8000/flash/
Request Method: GET
Status Code: 200 OK (from disk cache)

 

last 和 break關鍵字的區別

只用到了break,即匹配到此處后不會繼續跳。

permanent 和 redirect關鍵字的區別

  • rewrite … permanent 永久性重定向,請求日志中的狀態碼為301
  • rewrite … redirect 臨時重定向,請求日志中的狀態碼為302

我們常用的80端口轉443,即http轉https的一種配置方案為:

server {
    listen 80;
    server_name demo.com;
    rewrite ^(.*)$ https://${server_name}$1 permanent; 
}

 

會返回301永久重定向到對應的https:

Request URL: http://demo.com/flash/index.html
Request Method: GET
Status Code: 301 Moved Permanently
Location: https://demo/flash/index.html

 

一些使用場景

上述demo差不多就是我平時用的前后端分離的代理配置方案。下面是一些遇到過的場景。

配置一個靜態文件下載服務,我們下面軟件會經常看到index /的頁面。

server {
        listen       8888;        #端口
        server_name  _;   #服務名

        charset utf-8,gbk;
        root    /data/download;  #顯示的根索引目錄
        autoindex on;             #開啟索引功能
        autoindex_exact_size off; # 關閉計算文件確切大小(單位bytes),只顯示大概大小(單位kb、mb、gb)
        autoindex_localtime on;   # 顯示本機時間而非 GMT 時間
}

 

配置http重定向到https

server {
    listen 80;
    server_name demo.com;
    rewrite ^(.*)$ https://${server_name}$1 permanent; 
}
                   
server {
    listen       443;
    server_name  demo.com;
    charset utf-8;
    location / {
       alias   /data/web;
       index  index.html index.htm;
    }
}

 

配置靜態前端頁面

location / {
    alias   /data/web;
    index  index.html index.htm;
}

 

配置反向代理, 比如我們訪問http://demo.com/api/aaa/bbb,我們想要代理到http://api.com/api/aaa/bbb, 只切換了域名,uri相同。

upstream api_server {
  server 10.0.101.62:8081;
  server 10.0.101.61:8082;
}
location /api {
    proxy_pass  http://api_server;
    proxy_set_header Host $host;
    proxy_set_header  X-Real-IP        $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header  your-custome-header    "myHeader";
    proxy_set_header X-NginX-Proxy true;
}

 

配置反向代理時,移除前綴。比如我們的服務http://demo.com/users/aaa/bbb, 我們想要代理到http://users.com/aaa/bbb,即切換域名的同時,去掉users前綴。區別是proxy_pass 結尾的/.

location ^~/users/ {
    proxy_set_header Host $host;
    proxy_set_header  X-Real-IP        $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://users.com/;
}

 

反向代理時,想要自定義修改uri。使用rewrite正則修改。

# 修改uri,去掉了flash的前綴,$1表示正則匹配到的字符串內容。
location ^~ /flash/ {
    root   /data/flash/dist/;
    rewrite ^/flash/(.*)$  /$1 break;
    index  index.html index.htm;
}

 

 # 修改uri, 重新代理到新的地址 
location ^~/order/ {
    proxy_set_header Host $host;
    proxy_set_header  X-Real-IP        $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;

    rewrite ^/order/(.*)$ /$1 break;
    proxy_pass http://order;
}

 

代理跨域, 比如bing每日一圖,不支持我們ajax獲取圖片地址,我們可以自己寫一個支持的接口。

http://101.200.218.760/proxy/bing/HPImageArchive.aspx?format=js&idx=0&n=1

代理對象為:
https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1

location ^~/proxy/bing/ {
    add_header 'Access-Control-Allow-Origin' 'http://localhost:8088';
    add_header 'Cache-Control' 'public, max-age=604800';

    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    rewrite ^/proxy/bing/(.*)$ /$1 break;
    proxy_pass https://cn.bing.com/; 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM