一、前情提要#
上篇文章說到由於受不了網站加載速度,從而給網站加入了 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