Nginx反向代理及CORS跨域问题解决

2024 年 3 月 1 日 星期五(已编辑)
134
AI 生成的摘要
这篇文章上次修改于 2024 年 7 月 5 日 星期五,可能部分内容已经不适用,如有疑问可询问作者。

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查看控制台发现了这样一条报错信息:

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;
    }
}



🎉🎉🎉完结撒花🎉🎉🎉
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...