V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
stille
V2EX  ›  NGINX

CORS 跨域 POST 请求会出 OPTION 与请求,导致 2 次请求该如何优化?

  •  
  •   stille ·
    stilleshan · 2021-07-28 11:15:06 +08:00 · 2927 次点击
    这是一个创建于 1199 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前端 POST json 格式提交会发 OPTION 预请求,返回 200,在发主请求,导致后端收到两次请求.

    于是在 nginx 里配置如下:

        if ($request_method = 'OPTIONS') {
            proxy_pass http://127.0.0.1:33333;
        }
    
    	proxy_pass http://127.0.0.1:44444;
        
    

    第一次 OPTION 请求发给另外一个端口 33333,第二次请求发送给真正的后端 44444 ,是可以解决这个问题.

    但是 33333 这个端口要是 502 404 等错误,也会导致第二次请求发不出去..而且这么搞感觉也不优雅...

    在无法修改后端的情况下,还有什么方法能优化?

    18 条回复    2022-04-08 14:56:20 +08:00
    Terry05
        1
    Terry05  
       2021-07-28 11:17:28 +08:00
    我村的做法是检查到 methods = 'OPTIONS' 直接返回 204 状态
    TsubasaHanekaw
        2
    TsubasaHanekaw  
       2021-07-28 11:17:45 +08:00   ❤️ 1
    你都能改 nginx 了 为什么还要走 cors 跨域呢.
    creanme
        3
    creanme  
       2021-07-28 11:19:09 +08:00
    直接把前端请求转发到后端地址?这样就不会出现跨域了。
    TsubasaHanekaw
        4
    TsubasaHanekaw  
       2021-07-28 11:20:41 +08:00
    直接 nginx 就能返回 200
    if ($request_method = 'OPTIONS') {
    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header 'Access-Control-Allow-Headers' 'Content-Type';
    return 200;
    }
    sanmaozhao
        5
    sanmaozhao  
       2021-07-28 11:20:42 +08:00
    直接返回内容就行了啊,不用再转发给后端了。比如:

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Content-Length' 0;
    return 204;

    或者用这个思路:
    既然都有 nginx 了,不能把前端页面和转发的后端请求都放进来么?这样就不跨域了
    NjcyNzMzNDQ3
        6
    NjcyNzMzNDQ3  
       2021-07-28 11:21:45 +08:00
    按#1 的方法做就行,option 只是测试跨域的

    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;
    }
    stille
        7
    stille  
    OP
       2021-07-28 11:23:41 +08:00
    @Terry05 @sanmaozhao @NjcyNzMzNDQ3 @TsubasaHanekaw

    谢谢各位,刚发完贴我就想到这种直接 return 形式...果然..我去试试
    stille
        8
    stille  
    OP
       2021-07-28 11:24:10 +08:00
    @creanme
    @TsubasaHanekaw

    特殊情况,前后端不再一起也用的不同域名.
    also24
        9
    also24  
       2021-07-28 11:31:43 +08:00
    哈哈哈哈楼主这个提问,让我想起了 @mitu9527 的这个旧贴 https://www.v2ex.com/t/703603
    scemsjyd
        10
    scemsjyd  
       2021-07-28 11:31:45 +08:00
    OPTION 响应 Header 中通过下面这个属性控制 OPTION 请求的缓存时间
    Access-Control-Max-Age: 7200
    可以减少 OPTION 请求次数
    stille
        11
    stille  
    OP
       2021-07-28 11:41:16 +08:00
    @scemsjyd 嗯,这个配置过了..但过期或者首次还是会有问题.
    stille
        12
    stille  
    OP
       2021-07-28 11:41:58 +08:00
    @also24 谢谢.去看看
    also24
        13
    also24  
       2021-07-28 11:50:26 +08:00
    @stille #12
    那个主题下的回复方向相对比较散,建议先看 18# 我的回复 🙄
    qwerthhusn
        14
    qwerthhusn  
       2021-07-28 16:00:23 +08:00
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept,Origin,User-Agent,Cache-Control,X-User-Token,X-Transaction-ID,X-Requested-With' always;
    add_header 'Access-Control-Allow-Methods' '*' always;
    add_header 'Access-Control-Max-Age' '3600' always;

    if ($request_method = 'OPTIONS') {
    return 204;
    }


    1. Access-Control-Allow-Headers,如果你们的工程有自定义的头,需要加进去
    2. Access-Control-Max-Age 要设置有效时间,浏览器会记录此时间,在此时间内此域名不再发送 options 请求,不然每次请求都会重新发一次 OPTIONS
    stille
        15
    stille  
    OP
       2021-07-29 15:21:02 +08:00
    @qwerthhusn 奇怪了

    add_header 'Access-Control-Max-Age' '3600' always;

    设置了,但是每次请求还是有预请求
    qwerthhusn
        16
    qwerthhusn  
       2021-07-29 16:25:02 +08:00
    @stille 如果用的 F12 看的,先把 Disable Cache 不要勾选。让浏览器走缓存
    ch2
        17
    ch2  
       2021-07-29 18:00:56 +08:00
    OPTION 只要是跨域请求都会自动发的,这个是浏览器的机制
    vance123
        18
    vance123  
       2022-04-08 14:56:20 +08:00 via Android
    @qwerthhusn 纠正下,Access-Control-Max-Age 仅对单个资源也就是 url 有效,不同的 url 会发起新的 preflight 请求。

    https://stackoverflow.com/questions/42131714/cors-access-control-max-age-works-for-same-origin-or-just-same-request-url
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2688 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:00 · PVG 23:00 · LAX 07:00 · JFK 10:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.