寒武

寒武

Nginx反向代理及CORS跨域問題解決

一、前情提要#

上篇文章說到由於受不了網站加載速度,從而給網站加入了 CDN 之後。

https://www.xiaozhengyang.com/notes/5

我又陸陸續續將一些引用的外部資源也放到了又拍雲 OSS 中,比如字體文件,和博主正在做的 json 文件與 png 文件等。當我幾天後打開又拍雲控制台查看流量統計時,每天字體文件的請求流量竟然直接干到了總體流量 99.9% 的佔用,大約在 220M 左右,要知道這些流量只是我每天更新文章及測試網站速度所使用的。如果後期訪客量增加,或者被惡意刷流量,簡直不敢想一個月 15G 夠幹嘛的!必須得找一個解決法子了!

二、後端 Nginx 反代#

有 3 個解決方案
1.掏錢
==直接 pass==||(讓我掏錢不可能的,這輩子都不可能的~)||
2.更換為網路上免費的字體文件 CDN 地址
==直接 pass==||(先不說網路上大部分的地址都是 GitHub 以及 Jsdeliver,而且如果刪庫跑路了也很難及時發現)||
3.直接請求後端本地文件
==bingo!==(因為我的後端直接是家庭寬帶,100M 的上行帶寬何不利用起來呢?)

說幹就幹

在使用 Nginx 設置反代時遇到了個問題。

假如我設置了當前端訪問example.com/files時,便代理到後端的127.0.0.1/index地址。規則是這樣寫的

location ^~ /files/ {
    proxy_pass http://127.0.0.1/index; 
    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 REMOTE-HOST $remote_addr; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_http_version 1.1; 
    add_header X-Cache $upstream_cache_status; 
    add_header Strict-Transport-Security "max-age=31536000"; 
    add_header Cache-Control no-cache; 
}

乍一看沒有問題,但是當我們訪問此地址時就會報404 Not Found,查看一下控制台信息顯示 Nginx 路由到的地址是example.com/files/index。後端接收到的地址是直接把前端地址加進來了,所以就會 404。

解決這個問題很簡單,我們要在後端接收到的地址中排除掉前端反代時的後綴files。只需要在 proxy_pass 一行的請求地址最後面加上一個/即可。^~/files/ 表示匹配前綴是 user 的請求,proxy_pass 的結尾有 /,則會把 /files/* 後面的路徑直接拼接到後面,即移除 user。

location ^~ /files/ {
    proxy_pass http://127.0.0.1/index/; 
    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 REMOTE-HOST $remote_addr; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_http_version 1.1; 
    add_header X-Cache $upstream_cache_status; 
    add_header Strict-Transport-Security "max-age=31536000"; 
    add_header Cache-Control no-cache; 
}

這樣就可以順利訪問到後端地址了

三、CORS 跨域問題#

問題解決後,我們訪問博客前端地址,發現我們的字體文件仍然不能正確加載。F12查看控制台發現了這樣一條報錯信息:

::: banner {error}
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
:::

原因#

Note

被請求的資源沒有設置 ‘Access-Control-Allow-Origin’,也就是 nginx 的返回信息頭沒有 Access-Control-Allow-Origin

解決方案#

只需要在請求頭的位置加入以下代碼

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
 
    if ($request_method = 'OPTIONS') {
        return 204;
    }

語句解析#

Access-Control-Allow-Origin
伺服器默認是不被允許跨域的。給 Nginx 伺服器配置 Access-Control-Allow-Origin * 後,表示伺服器可以接受所有的請求源(Origin), 即接受所有跨域的請求。
Access-Control-Allow-Headers
是為了防止出現以下錯誤:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
這個錯誤表示當前請求 Content-Type 的值不被支持。其實是我們發起了 "application/json" 的類型請求導致的。這裡涉及到一個概念:預檢請求(preflight request), 請看下面 "預檢請求" 的介紹。
Access-Control-Allow-Methods
是為了防止出現以下錯誤:
Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
給 OPTIONS 添加 204 的返回
是為了處理在發送 POST 請求時 Nginx 依然拒絕訪問的錯誤
發送 "預檢請求" 時,需要用到方法 OPTIONS , 所以伺服器需要允許該方法。

四、完整代碼#

location ^~ /files/ {
   proxy_pass http://127.0.0.1/index/; 
   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 REMOTE-HOST $remote_addr; 
   proxy_set_header Upgrade $http_upgrade; 
   proxy_set_header Connection "upgrade"; 
   proxy_set_header X-Forwarded-Proto $scheme; 
   proxy_http_version 1.1; 
   add_header X-Cache $upstream_cache_status; 
   add_header Strict-Transport-Security "max-age=31536000"; 
   add_header Cache-Control no-cache; 
   add_header Access-Control-Allow-Origin *; 
   add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; 
   add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; 

   if ($request_method = 'OPTIONS') {
       return 204;
   }
}




🎉🎉🎉完結撒花🎉🎉🎉

此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://www.xiaozhengyang.com/posts/life/nginx.html


載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。