V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qq450255457
V2EX  ›  程序员

讨教 HTTP 中 OPTIONS 请求的优化?

  •  
  •   qq450255457 · 2019-12-27 16:42:43 +08:00 · 2934 次点击
    这是一个创建于 1791 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题发现场景

    前端在向后端发送 GET 请求,会多个 OPTIONS 请求,由于 OPTIONS 的时间和 GET 的时间接近,所以想优化它,让它只做一次 GET 请求。
    

    问题分析、优化

    • 在各种 google 之后,得知由于前端添加了头部 token 和 source 自定义字段,导致 GET 请求变为非简单请求,所以会在正式通信之前,添加一次 HTTP 预检请求,也就是 OPTIONS 请求。
    • 我尝试过不传 header 头时,确实只有一次 GET 请求,但由于业务需要,source 为必传字段,不然没法跟踪请求来源,当有 token 时,也必须要传
    • 试着把后端的 Access-Control-Max-Age 设置为 30 天,那样子虽然可以减少 OPTIONS 的请求,但只能减少非第一次请求的,在第一次请求依然会有

    想请教下各位大神有木有更好的解决方案?

    前端代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Vue-Test</title>
    <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    <script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
    </head>
    <body>
    <div id="app">
      {{ info }}
    </div>
    <script type = "text/javascript">
    axios.defaults.headers.common['source'] = 'test';
    var url = "https://api.rvhqs.com/v1/home_search_rv_detail/?vehicle_id=661&pickup_branch_id=387&start_date=2019-12-29&end_date=2020-01-01&return_branch_id=387&start_time=10:00&end_time=10:00"
    new Vue({
      el: '#app',
      data () {
        return {
          info: null
        }
      },
      mounted () {
        axios
          .get(url)
          .then(response => (this.info = response))
          .catch(function (error) { // 请求失败处理
            console.log(error);
          });
      }
    })
    </script>
    </body>
    </html>
    

    Django 后端 CORS 配置

    CORS_ORIGIN_ALLOW_ALL = True
    CORS_ALLOW_CREDENTIALS = True
    CORS_PREFLIGHT_MAX_AGE = 2592000
    CORS_ALLOW_HEADERS = default_headers + (
        'source',
    )
    
    13 条回复    2019-12-30 15:58:24 +08:00
    yeept
        1
    yeept  
       2019-12-27 16:51:01 +08:00
    可以使用 nginx 配置在一个域下,使用 CORS 的话还是会有 OPTIONS 请求
    IMCA1024
        2
    IMCA1024  
       2019-12-27 16:53:26 +08:00
    有点奇怪欸,为什么不从根本上解决这个接口时间问题。。。。。。
    ai277014717
        3
    ai277014717  
       2019-12-27 16:56:13 +08:00
    OPTIONS 是用来检查跨域权限的。收敛 url host 可解决吧。
    Chingim
        4
    Chingim  
       2019-12-27 16:57:49 +08:00
    1. 过早优化是万恶之源.
    2. 数据可以放 params 里, 不一定要放 Header 里, 也可以放 body
    HanMeiM
        5
    HanMeiM  
       2019-12-27 16:58:25 +08:00
    - -先去看看跨域吧
    HanMeiM
        6
    HanMeiM  
       2019-12-27 17:00:18 +08:00
    哦,骚凹瑞,没看中间部分。
    把 token 什么的放到 header 头里面,可以不用放 url,只要 url 没变是不会触发 options 的
    jinliming2
        7
    jinliming2  
       2019-12-27 23:03:17 +08:00 via iPhone
    1,网关层拦截所有 OPTIONS 请求,直接返回跨域授权信息,不要让 OPTIONS 请求进到业务代码里。
    2,遵从同源策略部署代码,当然这得看实际情况。
    3,将请求变为简单请求,不要使用特殊的 header 头,参数完全可以放在 query 参数或是 path 中。
    qq450255457
        8
    qq450255457  
    OP
       2019-12-30 14:07:01 +08:00
    @yeept 经过 google 查找后,通过 NGINX 把前后端置于一个域下,确实解决了 OPTIONS 请求的问题,谢谢。
    qq450255457
        9
    qq450255457  
    OP
       2019-12-30 14:08:19 +08:00
    @IMCA1024 该 API 接口耗时 75ms,加了个 OPTIONS 请求差不多 150ms.所以您说的接口是指什么呢?
    qq450255457
        10
    qq450255457  
    OP
       2019-12-30 14:08:46 +08:00
    @ai277014717 收敛 url host?
    qq450255457
        11
    qq450255457  
    OP
       2019-12-30 14:09:45 +08:00
    由于后端每个接口都需要参数 source,方便跟踪请求来源,那么你会把 source 放 body 中吗?
    qq450255457
        12
    qq450255457  
    OP
       2019-12-30 14:11:30 +08:00
    @jinliming2 您这是三种解决办法吗?
    jinliming2
        13
    jinliming2  
       2019-12-30 15:58:24 +08:00 via iPhone
    @qq450255457 是的,你 8 楼的解决方案就是我说的第二种,遵从同源策略,放到同一个域名下。
    你 9 楼的问题,加了 OPTIONS 请求时间翻倍,说明 OPTIONS 请求进入了业务逻辑,也就是没有区分 OPTIONS 请求和 GET 请求,导致业务处理了两遍。就是我说的第一种方案,网关层直接拦截 OPTIONS 请求返回跨域许可,这样服务端耗时就几乎为 0 了,只剩下一次请求来回的耗时。(当然,也有可能是其他原因)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5260 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:02 · PVG 15:02 · LAX 23:02 · JFK 02:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.