背景

有一个前后端分离的VUE项目来发送ajax请求, 查看Nginx日志或使用Chrome Dev Tools查看请求发送情况时, 会看到每次调后台API的请求之前, 都会发送一个OPTIONS请求, 无论API要求请求的方法是GET或POST.

为什么会发送这个OPTIONS请求? 困扰了项目组的前端同学和后端同学很久,今天正好听他们说起这个问题,就研究了一下原理。

过程

首先, 在js代码里是没写要发送OPTIONS请求的, 后台API要的请求方法不是GET就是POST, 也只发送过这两种类型的请求.

那么, 我就以为是前台调用方式的问题, 于是去看了看代码. 发现并没有什么很特殊的地方。然后直接看ajax.js文件. 结果, 发现一切正常, 并没有这种逻辑: 发送GET/POST请求之前, 先发送一个OPTIONS请求.

看来就不是前端同学写法的问题,也不是ajax的问题,仔细对比了一下之前的代码,发现唯一的区别就是ajax中用到了自定义的header头。

解惑

众所周知, ajax请求是由XMLHttpRequest对象实现的(部分低版本ID浏览器不是), 而XMLHttpRequest会遵守同源策略(same-origin policy). 也即脚本只能访问相同协议/相同主机名/相同端口的资源, 如果要突破这个限制, 那就是所谓的跨域, 此时需要遵守CORS(Cross-Origin Resource Sharing)机制。

那么, 允许跨域, 不就是服务端(例如Nginx或者后端代码)设置Access-Control-Allow-Origin: *就可以了吗?

普通的请求确实是这样子的, 除此之外, 还一种叫请求叫Preflighted Request(带预检的跨域请求)

Preflighted Request在发送真正的请求前, 会先发送一个方法为OPTIONS的预请求(Preflighted Request), 用于试探服务端是否能接受真正的请求.

如果options获得的回应是拒绝性质的,比如404\403\500等http状态,就会停止post、get等请求的发出。

那么, 什么情况下请求会变成Preflighted Request呢? 翻看了MDN的文档发现如下:(文档地址:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_request_headers)

  1. 请求方法不是GET/HEAD/POST
  2. POST请求的Content-Type并非application/x-www-form-urlencodedmultipart/form-data, 或text/plain
  3. 请求设置了自定义的header字段

举个例子, 如果POST请求要传输的数据为 XML文档, Content-Typeapplication/xmltext/xml, 则发送这个请求前会发送一个预请求,或者自定义的header字段也是一样的道理。

有了上面的知识点, 再去看项目中ajax调用

可以看出, 跨域请求中设置了自定义的header字段, 所以该请求是preflighted request, 则请求前一定会发送一个OPTIONS作为预请求.

所以说, 在项目中ajax对后台API的调用, OPTIONS请求是没办法去掉的, 除非后台接口不再需要在请求header中设置openId

但是由于该项目中用户信息是采用的JWT的方式,所以只好作罢。

但是由于该项目在后台中自定义了请求频率限制的拦截器,例如限制同一个客户端一秒内对某一个接口只能访问1次。如果超过限制,则第二次会返回状态码500,不予处理。如果每次请求前都带着一次OPTIONS请求,则该拦截器无法正常实现功能,反正会导致大批接口调用失败的情况。

鉴于上述分析,既然前端发起请求时OPTIONS请求没有办法去除,那么是否可以考虑从后台拦截器进行改造。

改造后的代码如下:

如果拦截到的请求不是项目中常规的GET或者POST请求,则该拦截器直接放行。至此,问题完美解决。希望可以帮到有类似问题的小伙伴~

AJAX请求中出现OPTIONS请求的更多相关文章

  1. 服务网关ZuulFilter过滤器--如何解决跨域请求中的OPTIONS请求

    进行跨域请求的时候,并且请求头中有额外参数,比如token,客户端会先发送一个OPTIONS请求 来探测后续需要发起的跨域POST请求是否安全可接受 所以这个请求就不需要拦截,下面是处理方式 @Ove ...

  2. Http中的options请求

    引自:https://www.jianshu.com/p/5cf82f092201.https://www.cnblogs.com/mamimi/p/10602722.html 一.options是什 ...

  3. HTTP协议以及HTTP请求中8种请求方法

    HTTP协议以及HTTP请求中8种请求方法 什么是协议? 协议,是指通信的双方,在通信流程或内容格式上,共同遵守的标准. 什么是http协议? http协议,是互联网中最常见的网络通信标准. http ...

  4. 请求时发送OPTIONS请求

    最近在用uni-app开发项目时,发现一个之前没注意到的点,当我发送POST请求的时候,在NetWork可以看到在发送正式的POST请求时,会先发送一个OPTIONS请求,OPTIONS请求后才会发送 ...

  5. HTTP协议---HTTP请求中的常用请求字段和HTTP的响应状态码及响应头

    http://blog.csdn.net/qxs965266509/article/details/8082810 用于HTTP请求中的常用请求头字段 Accept:用于高速服务器,客户机支持的数据类 ...

  6. postman简单教程,如何在请求中引用上次请求返回的值

    做接口测试,一定会遇到这种情况,需要拿上次请求的值在本次请求中使用,比如,我们去测试一个东西,要去登录才能做其他的操作,需要拿到登录返回数据中的某些字段,比如,token啊等... 如果发一次请求,就 ...

  7. postman的关联,即如何在请求中引用上次请求返回的值

    做接口测试,一定会遇到这种情况,需要拿上次请求的值在本次请求中使用,比如,我们去测试一个东西,要去登录才能做其他的操作,需要拿到登录返回数据中的某些字段,比如,token啊等... 如果发一次请求,就 ...

  8. 跨域请求中预检请求options之坑

    一.前言 因为跨域请求,浏览器可能(后面讲)会发送一次options请求,如果处理不好,跨域还是会gg的. 之前很少涉及跨域,涉及也是简单请求(下面阮老师文章中区别热简单请求和复杂请求),所以基本不会 ...

  9. SpringCloud+ZUUL跨域请求中的OPTIONS请求处理

    目前项目结构是VUE做前端,后端采用微服务架构,在开发时前端需要跨域请求数据,通过CorsConfig配置解决了简单跨域请求需要.但当需要在请求的header中增加token信息时,出现了请求失败的情 ...

随机推荐

  1. Java反射学习二

    利用反射进行对象拷贝的例子 如下例程ReflectTester类进一步演示了Reflection API的基本使用方法. ReflectTester类有一个copy(Object object)方法, ...

  2. typename在C++中的用法

    . //在C++中typename一般用来声明模板的模板参数(template parameter): template<typename T> class X; //T是一个模板参数 . ...

  3. java核心技术-多线程之线程基础

    说起线程,无法免俗首先要弄清楚的三个概念就是:进程.线程.协程.OK,那什么是进程,什么是线程,哪协程又是啥东西.进程:进程可以简单的理解为运行在操作系统中的程序,程序时静态代码,进程是动态运行着的代 ...

  4. Linux入门基础(一):Linux基本操作

    命令行BASH基本操作 Shell 用户不能直接操作内核,所以用户操作通过shell传递给内核 shell分为两种 : GUI 图形界面 (linux一般是GNOME) CLI 命令行界面 (linu ...

  5. 在 Mac 上通过 Docker 运行 Asp.net Core 简易教程

    首先,你需要在 Mac 上安装好 Docker 下载地址 https://download.docker.com/mac/stable/Docker.dmg 或者查看别人的 安装教程 怎么安装这里就不 ...

  6. 如何方便的结果ajax使用html5的新type类型

    今天需要做手机端的输入表单自动生成器,突然就想到了手机端对input的输入类型支持还不错,于是翻遍了资料,有了下面的使用方法,闲话少说,上正文: html5现在可以用的新input type类型一共有 ...

  7. lua通用数据类型

    TValue结构 TValue这个结构体是Lua的通用结构体,,Lua中的所有的数据都可以使用这个结构体来表示.很容易想到,在面向对象中,这个结构体是一个基类,派生出来的都是其他的子类. TValue ...

  8. 20155217 《信息安全系统设计基础》week16课堂测试

    20155217 <信息安全系统设计基础>week16课堂测试 在作业本上完成附图作业,要认真看题目要求并提交作业截图. 在set的过程中,我们需要将hour部分进行赋值,赋值我们采用&q ...

  9. OSG选取点云坐标不准的解决办法

    一.默认的相机和所有模型求交的方式 1.1 传统的模型与屏幕点求交的方法如下: osgViewer::View* viewer = dynamic_cast<osgViewer::View*&g ...

  10. 【转载】COM 组件设计与应用(十二)——错误与异常处理

    原文:http://vckbase.com/index.php/wv/1238.html 一.前言 程序设计中,错误处理必不可少,而且通常要占用很大的篇幅.本回书着落在 COM 中的错误(异常)的处理 ...