从前后端的角度分析options预检请求——打破前后端联调的理解障碍
文章目录
- 1.从前端的角度看options——post请求之前一定会有options请求?信口雌黄!
- 2.从后端的角度看options——post请求之前一定会有options请求?胡说八道!
1.从前端的角度看options——post请求之前一定会有options请求?信口雌黄!
你是否经常看到这种跨域请求错误?
这是因为服务器不允许跨域请求,这里会深入讲一讲OPTIONS
请求。
只有在满足一定条件的跨域请求中,浏览器才会发送OPTIONS
请求(预检请求)。这些请求被称为“非简单请求”。反之,如果一个跨域请求被认为是“简单请求”,那么浏览器将不会发送OPTIONS
请求。
简单请求需要满足以下条件:
- 只使用以下
HTTP
方法之一:GET
、HEAD
或POST
。 - 只使用以下
HTTP
头部:Accept
、Accept-Language
、Content-Language
、Content-Type
。 Content-Type
的值仅限于:application/x-www-form-urlencoded
、multipart/form-data
或text/plain
。
如果一个跨域请求不满足以上所有条件,那么它被认为是非简单请求。对于非简单请求,浏览器会在实际请求(例如PUT
、DELETE
、PATCH
或具有自定义头部和其他Content-Type
的POST
请求)之前发送OPTIONS
请求(预检请求)。
举个例子吧,口嗨半天是看不懂的,让我们看看 POST
请求在什么情况下不发送OPTIONS
请求
提示:当一个跨域POST
请求满足简单请求条件时,浏览器不会发送OPTIONS
请求(预检请求)。以下是一个满足简单请求条件的POST
请求示例:
// 使用Fetch API发送跨域POST请求
fetch("https://example.com/api/data", {method: "POST",headers: {"Content-Type": "application/x-www-form-urlencoded"},body: "key1=value1&key2=value2"
}).then(response => response.json()).then(data => console.log(data)).catch(error => console.error("Error:", error));
在这个示例中,我们使用Fetch API
发送了一个跨域POST
请求。请求满足以下简单请求条件:
- 使用
POST
方法。 - 使用的
HTTP
头部仅包括Content-Type
。 Content-Type
的值为"application/x-www-form-urlencoded
",属于允许的三种类型之一(application/x-www-form-urlencoded、multipart/form-data或text/plain
)。
因为这个请求满足了简单请求条件,所以浏览器不会发送OPTIONS
请求(预检请求)。
我们再看看什么情况下POST
请求之前会发送OPTIONS
请求,同样用代码说明,进行对比
提示:在跨域请求中,如果POST
请求不满足简单请求条件,浏览器会在实际POST
请求之前发送OPTIONS
请求(预检请求)。
// 使用Fetch API发送跨域POST请求
fetch("https://example.com/api/data", {method: "POST",headers: {"Content-Type": "application/json","X-Custom-Header": "custom-value"},body: JSON.stringify({key1: "value1",key2: "value2"})
}).then(response => response.json()).then(data => console.log(data)).catch(error => console.error("Error:", error));
在这个示例中,我们使用Fetch API
发送了一个跨域POST
请求。请求不满足简单请求条件,因为:
- 使用了非允许范围内的
Content-Type
值(“application/json
” 不属于application/x-www-form-urlencoded
、multipart/form-data
或text/plain
)。 - 使用了一个自定义
HTTP
头部 “X-Custom-Header
”,这不在允许的头部列表中。
因为这个请求不满足简单请求条件,所以在实际POST
请求之前,浏览器会发送OPTIONS
请求(预检请求)。
你可以按F12
直接在Console
输入查看Network
,尽管这个网址不存在,但是不影响观察OPTIONS
请求,对比一下我这两个例子。
总结:当进行非简单跨域POST
请求时,浏览器会在实际POST
请求之前发送OPTIONS
预检请求,询问服务器是否允许跨域POST
请求。如果服务器不允许跨域请求,浏览器控制台会显示跨域错误提示。如果服务器允许跨域请求,那么浏览器会继续发送实际的POST
请求。而对于满足简单请求条件的跨域POST
请求,浏览器不会发送OPTIONS
预检请求。
后端可以通过设置Access-Control-Max-Age
来控制OPTIONS
请求的发送频率。OPTIONS
请求没有响应数据(response data
),这是因为OPTIONS
请求的目的是为了获取服务器对于跨域请求的配置信息(如允许的请求方法、允许的请求头部等),而不是为了获取实际的业务数据,OPTIONS
请求不会命中后端某个接口。因此,当服务器返回OPTIONS
响应时,响应中主要包含跨域配置信息,而不会包含实际的业务数据
本地调试一下,前端发送POST
请求,后端在POST
方法里面打断点调试时,也不会阻碍OPTIONS
请求的返回
2.从后端的角度看options——post请求之前一定会有options请求?胡说八道!
在配置跨域时,服务器需要处理OPTIONS
请求,以便在响应头中返回跨域配置信息。这个过程通常是由服务器的跨域中间件(Node.js
—Express
框架的cors
中间件、Python
—Flask
框架的flask_cors
扩展)或过滤器(Java
—SpringBoot
框架的跨域过滤器)自动完成的,而无需开发人员手动处理。
以下是使用Spring Boot
的一个跨域过滤器,供参考
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class CorsConfig {public CorsConfig() {}@Beanpublic CorsFilter corsFilter() {// 1. 添加cors配置信息CorsConfiguration config = new CorsConfiguration();// Response Headers里面的Access-Control-Allow-Origin: http://localhost:8080config.addAllowedOrigin("http://localhost:8080");// 其实不建议使用*,允许所有跨域config.addAllowedOrigin("*");// 设置是否发送cookie信息,在前端也可以设置axios.defaults.withCredentials = true;表示发送Cookie,// 跨域请求要想带上cookie,必须要请求属性withCredentials=true,这是浏览器的同源策略导致的问题:不允许JS访问跨域的Cookie/*** withCredentials前后端都要设置,后端是setAllowCredentials来设置* 如果后端设置为false而前端设置为true,前端带cookie就会报错* 如果后端为true,前端为false,那么后端拿不到前端的cookie,cookie数组为null* 前后端都设置withCredentials为true,表示允许前端传递cookie到后端。* 前后端都为false,前端不会传递cookie到服务端,后端也不接受cookie*/// Response Headers里面的Access-Control-Allow-Credentials: trueconfig.setAllowCredentials(true);// 设置允许请求的方式,比如get、post、put、delete,*表示全部// Response Headers里面的Access-Control-Allow-Methods属性config.addAllowedMethod("*");// 设置允许的header// Response Headers里面的Access-Control-Allow-Headers属性,这里是Access-Control-Allow-Headers: content-type, headeruserid, headerusertokenconfig.addAllowedHeader("*");// Response Headers里面的Access-Control-Max-Age:3600// 表示下回同一个接口post请求,在3600s之内不会发送options请求,不管post请求成功还是失败,3600s之内不会再发送options请求// 如果不设置这个,那么每次post请求之前必定有options请求config.setMaxAge(3600L);// 2. 为url添加映射路径UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource();// /**表示该config适用于所有路由corsSource.registerCorsConfiguration("/**", config);// 3. 返回重新定义好的corsSourcereturn new CorsFilter(corsSource);}
}
这里setMaxAge
方法来设置预检请求(OPTIONS
请求)的有效期,当浏览器第一次发送非简单的跨域POST
请求时,它会先发送一个OPTIONS
请求。如果服务器允许跨域,并且设置了Access-Control-Max-Age
头(设置了setMaxAge
方法),那么浏览器会缓存这个预检请求的结果。在Access-Control-Max-Age
头指定的时间范围内,浏览器不会再次发送OPTIONS
请求,而是直接发送实际的POST
请求,不管POST
请求成功还是失败,在设置的时间范围内,同一个接口请求是绝对不会再次发送OPTIONS
请求的。
后端需要注意的是,我这里设置允许请求的方法是config.addAllowedMethod("*")
,*
表示允许所有HTTP
请求方法。如果未设置,则默认只允许“GET
”和“HEAD
”。你可以设置的HTTPMethod
为GET
, HEAD
, POST
, PUT
, PATCH
, DELETE
, OPTIONS
, TRACE
经过我的测试,OPTIONS
无需手动设置,因为单纯只设置OPTIONS
也无效。如果你设置了允许POST
,代码为config.addAllowedMethod(HttpMethod.POST);
那么其实已经默认允许了OPTIONS
,如果你只允许了GET
,尝试发送POST
请求就会报错。
举个例子,这里只允许了GET
请求,当我们尝试发送一个POST
非简单请求,预检请求返回403
,服务器拒绝了OPTIONS
类型的请求,因为你只允许了GET
,未配置允许OPTIONS
请求,那么浏览器将收到一个403 Forbidden
响应,表示服务器拒绝了该OPTIONS
请求,POST
请求的状态显示CORS error
在Spring Boot
中,配置允许某个请求方法(如POST
、PUT
或DELETE
)时,OPTIONS
请求通常会被自动允许。这意味着在大多数情况下,后端开发人员不需要特意考虑OPTIONS
请求。这种自动允许OPTIONS
请求的行为取决于使用的跨域处理库或配置,最好还是显式地允许OPTIONS
请求。
欢迎一键三连~
有问题请留言,大家一起探讨学习
转载请注明:https://blog.csdn.net/qq_34115899/article/details/116763968
----------------------Talk is cheap, show me the code-----------------------
从前后端的角度分析options预检请求——打破前后端联调的理解障碍相关推荐
- 对CORS OPTIONS预检请求的一些思考
前后端分离模大势所趋,跨域问题更是老生常谈. <程序员应对浏览器同源策略的姿势>一文提到三种跨域请求方案,重点讲述了w3c和浏览器厂商推出的CORS规范. 同源策略 所谓同源是指域名.协 ...
- OPTIONS预检请求
1.options请求是什么?什么时候浏览器会发送预检请求 options是预检请求,在真正的请求发送出去之前,浏览器都会先发送一个options请求 向服务器询问此接口是否允许我访问.浏览器在当前真 ...
- 什么时候会发送options请求(预检请求)
OPTIONS请求即预检请求,可用于检测服务器允许的http方法.当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起OPTIONS请求,即CORS预检请求,服务器若接受该跨 ...
- 跨域请求避免OPTIONS请求(预检请求)
有时候前后端分离域名不一致,会造成跨域请求 而跨域请求有时候会自动发起两次请求,第一次为预检请求,即OPTIONS请求 一般来说使用 application/json 的 post 请求是必然会带入O ...
- vue跨域拦截浏览器options预检
当你跨域访问接口的时候,会发现你的接口请求了两次,然后仔细对比一下会发现请求类型并不一致,一个是OPTIONS,另一个是你的POST请求.事情是这样发生的,当浏览器发现你准备跨域进行非简单请求的时候( ...
- CORS预检请求详谈
引言 最近在项目中因前后端部署不同地方,前端在请求后端api时发生了跨域请求,我们采用CORS(跨域资源共享)来解决跨域请求,这需要前后端的配合来完成.在这一过程中,后端支持了CORS跨域请求后,前端 ...
- node --- [跨域] 预检请求
简单请求 若满足所有下述条件,则该请求可视为"简单请求": 使用下列方法之一: GET HEAD POST Content-Type: (仅当POST方法的Content-Type ...
- 对预检请求的响应未通过访问控制检查
本文翻译自:Response to preflight request doesn't pass access control check I'm getting this error using n ...
- 最近很火的在线文件预览txt、doc、ppt、pdf、excel、jpg、png、zip、tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写搜索引擎多关键词检索名称和内容(四)
最近很火的在线文件预览txt.doc.ppt.pdf.excel.jpg.mp4.png.zip.tar.gz等各种文件及压缩文件在线解压和预览,包括前后端设计和源码,编写一个文件搜索引擎实现多关键词 ...
最新文章
- 这些超级高效的人工神经元不使用电子?
- centos6.5 install mongodb
- 利用System.EventHandler来实现两个窗体间的事件调用
- python编程从入门到精通 叶维忠 pdf-叶维忠《Python编程从入门到精通》PDF
- BZOJ 2045 容斥原理
- HTTP请求和标头参数的CDI拦截器-简单示例
- JAVA第三方包导入但找不到类,解决:导入第三方包报错java.lang.NoClassDefFoundError:XXX.XXX,XXXXXX...
- CRM客户关系管理系统HR人事OA系统APP源码
- Wowza服务器系列(4):使用rtmp协议向wowza推流的wowoza配置方法
- 什么是数字式射频信号发生器
- (转)清华博士王垠的退学申请——研究生,无论你想不想搞研究,都该读读这篇文章。
- MySQL - 基于ibd文件恢复表数据
- 微型计算机扫描方法,微机习题课(键盘-8255A行扫描法).ppt
- 传鸿蒙操作系统掌舵人王成录已从华为离职
- 无法解析域名“cn.archive.ubuntu.com”。
- 初识Navigation(导航)
- 防静电手环在计算机中的功能,无线静电手环是怎样防静电的原理是什么
- springBoot 全局异常处理 报错 : Could not resolve method parameter at index 0 in public .....
- 常用软件:推荐七款装机必备的软件
- 软文发布的方法以及技巧总结