nginx 之 proxy_pass 接口轉發的規則

今天上了一個多頁應用,發現接口轉發後是 401。 最後發現是接口轉發出錯了。地址裏多拼了一個 路徑。 之前我一直覺得location 字段會替換掉 proxy_pass 裏面配置的 url 地址。 今天瞭解了一下 發現仍是有很多細節的。html

// node js 文件,打印請求路徑。方便查看後端真實接受到的請求地址
const http = require('http');
http.createServer((req, res) => {
  console.log(req.url);
  res.end(`您的 請求 地址是${req.url}`);
}).listen(3000);

proxy_pass 如何轉發,首先看 proxy_pass 的url 配置。node

proxy_pass 只是HOST

proxy_pass 只是HOST,不包含任何路徑,好比nginx

* http://host - √
* https://host - √
* http://host:port - √
* https://host:port - √
* http://host/ - x
* http://host:port/ - x

這種狀況下,會把匹配到的全部路徑直接穿透轉發。好比如下的配置git

location /api/ {
    proxy_pass http://127.0.0.1:3000;
 }

訪問 http://127.0.0.1:80/api/cc, 後端結果爲 您的 請求 地址是/api/ccgithub

proxy_pass 包含路徑

這裏的路徑哪怕只是一個 / 也是存在的,如:express

這種狀況下,url 裏面會去掉 location 匹配的字符串,拼接到 proxy_pass 再進行轉發。後端

location /api/ {
    proxy_pass http://127.0.0.1:3000/;
 }

訪問 http://127.0.0.1:81/api/cc, 後端結果爲 您的 請求 地址是/ccapi

重寫代理連接 - url rewrite

使用 rewrite 指令而且生效後,proxy_pass url 連接中的路徑會被忽略,如:ide

server {
            listen       83;
            location / {
                rewrite ^/api/(.*) /fixpath=$1 break;
                proxy_pass http://127.0.0.1:3000/node/;
            }
            location ^/api/ {
                rewrite ^/api/(.*) /fixpath=$1 break;
                proxy_pass http://127.0.0.1:3000/node/;
            }
        }

訪問 http://127.0.0.1:83/bb/cc 獲得 您的 請求 地址是/node/bb/cc(匹配上 / 了,沒有匹配 rewrite)
訪問 http://127.0.0.1:83/api/cc 獲得 您的 請求 地址是/fixpath=cc (咱們寫的 proxy_pass http://127.0.0.1:3000/node/ 裏面的 node路徑丟失了 )post

知道了這幾點,碰到轉發接口也有一點底氣啦~

更多

在github上看到的這本小書 ⬇️
(參考資料)[https://xuexb.github.io/learn...]

個人 nginx 配置

events {
}
http {
    # proxy_pass url 只是 host
    # 這時候 location 匹配的完整路徑將直接透傳給 url ,如:
     server {
            listen       80;
            
            location / {
                proxy_pass http://127.0.0.1:3000;
            }

            location /api/ {
                proxy_pass http://127.0.0.1:3000;
            }
           
            
        }
    # url 包含路徑
    # 當 proxy_pass url 的 url 包含路徑時,匹配時會根據 location 的匹配後的連接透傳給 url ,注意匹配後就是這樣:
     server {
            listen       81;
            
            location / {
                proxy_pass http://127.0.0.1:3000/;
            }

            location /api/ {
                proxy_pass http://127.0.0.1:3000/;
            }
            location /bpi/ {
                proxy_pass http://127.0.0.1:3000/v1;
            }
            location /cpi {
                proxy_pass http://127.0.0.1:3000/v1;
            }
        }
        # 當 location 以正則形式匹配時,proxy_pass 就不能以 / 結束了,也就是不能包含路徑了, 會提示配置錯誤,好比錯誤的:

     server {
            listen       82;
            
            location / {
                proxy_pass http://127.0.0.1:3000/;
            }
        # nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /test.conf:47
        #    location ~* ^/api/ {
        #         proxy_pass http://127.0.0.1:3000/;
        #     }

        # nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /Users/tangdaoyuan/code/anheng/jz-bingjiang/test.conf:52
        #    location ~* ^/api/ {
        #         proxy_pass http://127.0.0.1:3000/b1;
        #     }
        }

    # 使用 rewrite 指令而且生效後,proxy_pass url 連接中的路徑會被忽略,如:
     server {
            listen       83;
            location / {
                proxy_pass http://127.0.0.1:3000/node/;
            }
            location ^/api/ {
                rewrite ^/api/(.*) /fixpath=$1 break;
                proxy_pass http://127.0.0.1:3000/node/;
            }
        }

}

測試流程 : node 運行 服務, 啓動Nginx 轉發 , 再用postman 發送請求。

相關文章
相關標籤/搜索