本文環境比較復雜,首先兩層nginx轉發,並且訪問路徑也不是根路徑。加上對nginx一知半解,各路搜索一看,全程懵逼。最終沒有一個能用的。最后還是靠同事幫助,文檔大法結束加班。本文知識點:location優先級,nginx資源文件尋找方式,rewrite 重定向問題。
location 優先級
- = 開頭表示精確匹配
- ^~ 開頭表示uri以某個常規字符串開頭,理解為匹配 url路徑即可。nginx不對url做編碼,因此請求為/static/20%/aa,可以被規則^~ /static/ /aa匹配到(注意是空格)。以xx開頭
- ~ 開頭表示區分大小寫的正則匹配 以xx結尾
- ~* 開頭表示不區分大小寫的正則匹配 以xx結尾
- !~和!~*分別為區分大小寫不匹配及不區分大小寫不匹配 的正則
- / 通用匹配,任何請求都會匹配到。
try_file 使用
當用戶請求 http://localhost/example 時,這里的 $uri 就是 /example。
try_files 會到硬盤里嘗試找這個文件。如果存在名為 /$root/example(其中 $root 是項目代碼安裝目錄)的文件,就直接把這個文件的內容發送給用戶。
顯然,目錄中沒有叫 example 的文件。然后就看 $uri/,增加了一個 /,也就是看有沒有名為 /$root/example/ 的目錄。
又找不到,就會 fall back 到 try_files 的最后一個選項 /index.php,發起一個內部 “子請求”,也就是相當於 nginx 發起一個 HTTP 請求到 http://localhost/index.php。
適配react-router browserrouter配置
首先文件存放路徑是子目錄 /usr/local/services/app_logical_server-1.0/bin/app/screen
訪問路徑是 https://example.com/app/screen/
錯誤的nginx 配置
server { listen 8080; root /usr/local/services/app_logical_server-1.0/bin/app/screen; location ~* \.(gif|jpg|png|js|css)$ { root /usr/local/services/app_logical_server-1.0/bin/app/screen/; } location ^~ /app/screen { root html; index index.html; try_files $uri $uri/ /index.html; } }
錯誤點
錯誤現象是index.html可以找到,但是index.html中的js寫的是相對路徑,導致所有的靜態資源文件也進入了第二個location,導致頁面白屏。
分析如下。
1.優先級問題
首先匹配 =,其次匹配^~, 其次是按文件中順序的正則匹配,最后是交給 / 通用匹配。當有匹配成功時候,停止匹配,按當前匹配規則處理請求。
~* 的優先級低於 ^~所以第一個配置靜態資源文件雖然寫在前面,還是不會進去的。
2. server root 配置錯誤
解決優先級問題后,問題依然存在。原因就是這個。root 在server和location中都有,都是配置文件開始尋找的根路徑,如果url是https://xxxx:8084/app/screen,location中的配置優先級高於server。首先會進入第二個location中,尋找文件,文件路徑是root和域名后面的路徑的拼接,例如:訪問路徑是 https://example.com/app/screen/umi.js,server root 為 /usr/local/services/app_logical_server-1.0/bin/app/screen。 nginx尋找文件的地址為/usr/local/services/app_logical_server-1.0/bin/app/screen/app/screen/umi.js.當然找不到,報404錯誤。
正確的配置
server { listen 8084; root /usr/local/services/app_logical_server-1.0/bin/; location ~* \.(gif|jpg|png|js|css)$ { root /usr/local/services/app_logical_server-1.0/bin; } location ~* /app/screen { #try_files $uri $uri/ /usr/local/services/app_logical_server-1.0/bin/app/screen/index.html; root /usr/local/services/app_logical_server-1.0/bin; try_files /app/screen/index.html =404; } }
廣州品牌設計公司https://www.houdianzi.com PPT模板下載大全https://redbox.wode007.com
不帶/的url重定向問題
當前配置還有個問題,就是末尾不帶斜杠時,index.html可以加載到,但是html中的資源文件寫的相對路徑,當url 為https://example/app/screen時,相對路徑為https://example/app,以js為例,https://example/app/umi.js,所以報404錯誤。 解決方案為,利用location優先級,再加一個 = /app/screen 的location 。
location = /sa/screen { rewrite ^([^.]*[^/])$ $1/ permanent; port_in_redirect off; }
但是到此還沒結束。因為業務需要,本層nginx前面還有一層Nginx。所以301 重定向的時候,會帶上端口號。導致找不到請求。port_in_redirect off; 配置可以解決此問題
最終版完美配置
server { listen 8084; root /usr/local/services/app_logical_server-1.0/bin/; location = /sa/screen { rewrite ^([^.]*[^/])$ $1/ permanent; port_in_redirect off; } location ~* \.(gif|jpg|png|js|css)$ { root /usr/local/services/app_logical_server-1.0/bin; } location ~* /app/screen { #try_files $uri $uri/ /usr/local/services/app_logical_server-1.0/bin/app/screen/index.html; root /usr/local/services/app_logical_server-1.0/bin; try_files /app/screen/index.html =404; } }