qq450255457
V2EX  ›  程序员

讨教 HTTP 中 OPTIONS 请求的优化?

By qq450255457 at 2019 年 12 月 27 日 · 4044 次点击

问题发现场景

前端在向后端发送 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 日
可以使用 nginx 配置在一个域下,使用 CORS 的话还是会有 OPTIONS 请求
IMCA1024
   2
IMCA1024  
   2019 年 12 月 27 日
有点奇怪欸,为什么不从根本上解决这个接口时间问题。。。。。。
ai277014717
   3
ai277014717  
   2019 年 12 月 27 日
OPTIONS 是用来检查跨域权限的。收敛 url host 可解决吧。
Chingim
   4
Chingim  
   2019 年 12 月 27 日
1. 过早优化是万恶之源.
2. 数据可以放 params 里, 不一定要放 Header 里, 也可以放 body
HanMeiM
   5
HanMeiM  
   2019 年 12 月 27 日
- -先去看看跨域吧
HanMeiM
   6
HanMeiM  
   2019 年 12 月 27 日
哦,骚凹瑞,没看中间部分。
把 token 什么的放到 header 头里面,可以不用放 url,只要 url 没变是不会触发 options 的
jinliming2
   7
jinliming2  
   2019 年 12 月 27 日 via iPhone
1,网关层拦截所有 OPTIONS 请求,直接返回跨域授权信息,不要让 OPTIONS 请求进到业务代码里。
2,遵从同源策略部署代码,当然这得看实际情况。
3,将请求变为简单请求,不要使用特殊的 header 头,参数完全可以放在 query 参数或是 path 中。
qq450255457
   8
qq450255457  
OP
   2019 年 12 月 30 日
@yeept 经过 google 查找后,通过 NGINX 把前后端置于一个域下,确实解决了 OPTIONS 请求的问题,谢谢。
qq450255457
   9
qq450255457  
OP
   2019 年 12 月 30 日
@IMCA1024 该 API 接口耗时 75ms,加了个 OPTIONS 请求差不多 150ms.所以您说的接口是指什么呢?
qq450255457
   10
qq450255457  
OP
   2019 年 12 月 30 日
@ai277014717 收敛 url host?
qq450255457
   11
qq450255457  
OP
   2019 年 12 月 30 日
由于后端每个接口都需要参数 source,方便跟踪请求来源,那么你会把 source 放 body 中吗?
qq450255457
   12
qq450255457  
OP
   2019 年 12 月 30 日
@jinliming2 您这是三种解决办法吗?
jinliming2
   13
jinliming2  
   2019 年 12 月 30 日 via iPhone
@qq450255457 是的,你 8 楼的解决方案就是我说的第二种,遵从同源策略,放到同一个域名下。
你 9 楼的问题,加了 OPTIONS 请求时间翻倍,说明 OPTIONS 请求进入了业务逻辑,也就是没有区分 OPTIONS 请求和 GET 请求,导致业务处理了两遍。就是我说的第一种方案,网关层直接拦截 OPTIONS 请求返回跨域许可,这样服务端耗时就几乎为 0 了,只剩下一次请求来回的耗时。(当然,也有可能是其他原因)
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
© 2026 V2EX · 36ms · 3.9.8.5