Nginx反向代理及CORS跨域问题解决
一、前情提要
上篇文章说到由于受不了网站加载速度,从而给网站加入了CDN之后。
https://www.xiaohanwu.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
查看控制台发现了这样一条报错信息:
原因
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;
}
}