http请求发生了两次(options请求)
前言
自后台restful接口流行开来,请求了两次的情况(options请求)越来越普遍。笔者也在实际的项目中遇到过这种情况,做一下整理总结。

文章书写思路:

为什么发生两次请求
http的请求方式,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT等八种请求方式。其中,get与post只是我们常用的请求方式。
我们能在图一里看到,第一条的请求方式为options,第二条请求,才是我们预想中的请求。所以为什么发生两条请求的原因就变成了为什么发生options请求。
options请求
options请求的官方定义:OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。
用白话说就是:在发生正式的请求之前,先进行一次预检请求。看服务端返回一些信息,浏览器拿到之后,看后台是否允许进行访问。
如何产生options请求:
产生options请求的原因包括以下几条:
1:产生了复杂请求。复杂请求对应的就是简单请求。简单请求的定义是:
- 请求方法是GET、HEAD或者POST,并且当请求方法是POST时,Content-Type必须是application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值。
- 请求中没有自定义HTTP头部。
所谓的自定义头部,在实际的项目里,我们经常会遇到需要在header头部加上一些token或者其他的用户信息,用来做用户信息的校验。
2:发生了跨域。
options请求有什么作用
官方将头部带自定义信息的请求方式称为带预检(preflighted)的跨域请求。在实际调用接口之前,会首先发出一个options请求,检测服务端是否支持真实的请求进行跨域的请求。真实请求在options请求中,通过request-header将 Access-Control-Request-Headers与Access-Control-Request-Method发送给后台,另外浏览器会自行加上一个Origin请求地址。服务端在接收到预检请求后,根据资源权限配置,在response-header头部加入access-control-allow-headers(允许跨域请求的请求头)、access-control-allow-methods(允许跨域请求的请求方式)、access-control-allow-origin(允许跨域请求的域)。另外,服务端还可以通过Access-Control-Max-Age来设置一定时间内无须再进行预检请求,直接用之前的预检请求的协商结果即可。浏览器再根据服务端返回的信息,进行决定是否再进行真实的跨域请求。这个过程对于用户来说,也是透明的。
另外在HTTP响应头,凡是浏览器请求中携带了身份信息,而响应头中没有返回Access-Control-Allow-Credentials: true的,浏览器都会忽略此次响应。
总结:只要是带自定义header的跨域请求,在发送真实请求前都会先发送OPTIONS请求,浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。所以复杂请求肯定会两次请求服务端。
options请求如何避免
其实通过以上的分析,我们能得出以下解决方案:
1:使用代理,避开跨域。
2:将复杂跨域请求更改为简单跨域请求。
3:不使用带自定义配置的header头部。
实际案例
笔者现在维护的项目之一是用angularjs作为框架,使用$resoruce进行的通信,请求头默认采用content-type: application/json。所以即使拿掉请求头里前台自定义的token,仍然还会在post请求中额外发出options请求,因为不满足简单请求的条件。而get请求没有这这个情况。

笔者将header头里的token拿掉后,get的options请求消除了。

上图中,post发出了options请求。原因在于content-type。
去除post的options请求:

有人想问不想用options请求,却又想验证用户信息该怎么做呢?这个时候考虑通过cookie进行。
http请求发生了两次(options请求)的更多相关文章
- easyui datagrid 加载两次请求,触发两次ajax 请求 问题
datagrid初始化的时候请求两次URL 两种情况 1. <table id="gridview" class="easyui-datagrid"> ...
- Http中的options请求
引自:https://www.jianshu.com/p/5cf82f092201.https://www.cnblogs.com/mamimi/p/10602722.html 一.options是什 ...
- ( 转 ) CORS 有一次 OPTIONS 请求的原理
刚接触前端的时候,以为HTTP的Request Method只有GET与POST两种,后来才了解到,原来还有HEAD.PUT.DELETE.OPTIONS-- 目前的工作中,HEAD.PUT.DELE ...
- http跨域时的options请求
1.背景 在前后端分离的项目中经常会遇到跨域请求的问题,如果没有进行跨域配置,会浏览器请求失败.我一般采用两种解决方案: 1.采用nginx进行转发,是前后端服务处于同一个域下面,从根本上避免跨域问题 ...
- AJAX请求中出现OPTIONS请求
背景 有一个前后端分离的VUE项目来发送ajax请求, 查看Nginx日志或使用Chrome Dev Tools查看请求发送情况时, 会看到每次调后台API的请求之前, 都会发送一个OPTIONS请求 ...
- 记一次 CORS 跨域请求出现 OPTIONS 请求的问题及解决方法
今天前后端在联调接口的时候,发生了跨域请求资源获取不到的问题. 首先说明下跨域问题的由来.引自HTTP 访问控制 的一段话: 当 Web 资源请求由其它域名或端口提供的资源时,会发起跨域 HTTP 请 ...
- OPTIONS 请求引发的分析
阅读提纲: 为什么会出现 OPTIONS 请求? 什么情况下会出现 OPTIONS 请求? OPTIONS 请求会发送什么内容? 跨域前端访问后端时,所有的 Ajax HTTP 请求都会先发送一个 O ...
- Network出现两次相同请求?
出现的状况 Network中出现了两个相同的请求(如图),两个发起了同样的请求,花的时间却不同,一个55ms,一个花了294ms. 两个相同的请求 什么情况啊?研究了一番,我发现有一个地方是不同的 ...
- problem:为什么会有options请求
为了安全考虑,浏览器对资源访问有同源限制的问题,也就是web应用程序只能访问和它同一协议同一域名同一端口的web应用程序上的资源. 通过跨域资源共享机制可以让资源在浏览器中访问与该资源本身不同域的资源 ...
随机推荐
- cowsay
# apt install cowsay sl cmatrix $ cowsay "hello~" $ find /usr/share/cowsay/cows -iname &qu ...
- oom_killer
Limited Memory 今天在虚拟机里面用Word处理文档的时候,突然硬盘灯一阵狂闪,然后虚拟机就一起消失了. 这种事情屡见不鲜,很明显是Linux内核把占用最多内存的程序(这次是Virtual ...
- Matlab 一些函数
max(A,[],dim):dim取1或2.dim取1时,该函数和max(A)完全相同:dim取2时,该函数返回一个列向量,其第i个元素是A矩阵的第i行上的最大值.
- Highcharts 时间序列,可缩放的图表;Highcharts X 轴翻转曲线图;Highcharts 带标记曲线图
Highcharts 时间序列,可缩放的图表 配置 图表 配置可缩放图表. chart.zoomType 指定了用户可以拖放的尺寸,用户可以通过拖动鼠标来放大,可能值是x,y或xy: var char ...
- 015——数组(十五)sort natsort shuffle natcasesoft array_multisort
<?php /*数组排序函数 * sort natsort shuffle natcasesoft array_multisort */ //sort() 对数组元素进行递增的排序, /*$ar ...
- 使用minidom来处理XML的示例
http://www.cnblogs.com/xuxm2007/archive/2011/01/16/1936610.html http://blog.csdn.net/ywchen2000/arch ...
- vue环境的搭建
一.首先要安装nodejs : 别去官网下,慢的要死,这是国内的什么版本都有.地址 这是我下载的. 然后就傻瓜式安装. 验证是否安装成功 二.node.js的环境变量的新建. //我安装的路径是D: ...
- zset类型以及其操作
sorted set类型 sorted sets类型以及其操作zset是set的一格升级版本,它在set的基础上增加了一格顺序属性,这一属性在添加元素的同时可以指定,每次指定后,zset会自动重新按照 ...
- (转)Android学习笔记②——HelloWorld的创建已经基本知识
开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程:接下来需要输入应用名称(第一个字母要大写) ...
- Flask框架中特有的变量/函数及上下文
模板中特有的变量和函数 你可以在自己的模板中访问一些 Flask 默认内置的函数和对象 config 你可以从模板中直接访问Flask当前的config对象: {{config.SQLALCHEMY_ ...