寒武

寒武

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


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。