http请求发生了两次(options请求)

前言

自后台restful接口流行开来,请求了两次的状况(options请求)愈来愈广泛。笔者也在实际的项目中遇到过这种状况,作一下整理总结。angularjs

文章书写思路:

为何发生两次请求

http的请求方式,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT等八种请求方式。其中,get与post只是咱们经常使用的请求方式。json

咱们能在图一里看到,第一条的请求方式为options,第二条请求,才是咱们预想中的请求。因此为何发生两条请求的缘由就变成了为何发生options请求。跨域

 options请求

options请求的官方定义:OPTIONS方法是用于请求得到由Request-URI标识的资源在请求/响应的通讯过程当中可使用的功能选项。经过这个方法,客户端能够在采起具体资源请求以前,决定对该资源采起何种必要措施,或者了解服务器的性能。浏览器

用白话说就是:在发生正式的请求以前,先进行一次预检请求。看服务端返回一些信息,浏览器拿到以后,看后台是否容许进行访问。服务器

如何产生options请求:

产生options请求的缘由包括如下几条:restful

1:产生了复杂请求。复杂请求对应的就是简单请求。简单请求的定义是:cookie

  1.  请求方法是GET、HEAD或者POST,而且当请求方法是POST时,Content-Type必须是application/x-www-form-urlencoded, multipart/form-data或着text/plain中的一个值。
  2.  请求中没有自定义HTTP头部。

所谓的自定义头部,在实际的项目里,咱们常常会遇到须要在header头部加上一些token或者其余的用户信息,用来作用户信息的校验。app

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来设置必定时间内无须再进行预检请求,直接用以前的预检请求的协商结果便可。浏览器再根据服务端返回的信息,进行决定是否再进行真实的跨域请求。这个过程对于用户来讲,也是透明的。post

另外在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进行。

相关文章
相关标签/搜索