风过空庭,字句正徐来。
关于🎃关于本站关于我
更多✨时间线友链🚇开往
联系📞写留言发邮件GitHub
© 2021-2026 肖寒武. | RSS 订阅 | 站点地图 | | Stay hungry. Stay foolish.
Powered by Mix Space&
白い
.
| 豫ICP备2024044709号 |
正在被0人看爆
纸白微明,未成篇章。

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

(已编辑)
254
AI·GEN

关键洞察

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

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • 一、前情提要

    上篇文章说到由于受不了网站加载速度,从而给网站加入了CDN之后。

    我又陆陆续续将一些引用的外部资源也放到了又拍云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地址。规则是这样写的

    NGINX
    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。只需要在proxypass一行的请求地址最后面加上一个/即可。^~/files/表示匹配前缀是user的请求,proxypass的结尾有/, 则会把/files/*后面的路径直接拼接到后面,即移除user。

    NGINX
    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

    解决方案

    只需要在请求头的位置加入以下代码

    NGINX
    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 ,所以服务器需要允许该方法。

    四、完整代码

    CodeBlock Loading...



    🎉🎉🎉完结撒花🎉🎉🎉
    NGINX
    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;
        }
    }