从前后端的角度分析options预检请求

这篇具有很好参考价值的文章主要介绍了从前后端的角度分析options预检请求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

摘要:options预检请求是干嘛的?options请求一定会在post请求之前发送吗?前端或者后端开发需要手动干预这个预检请求吗?不用文档定义堆砌名词,从前后端角度单独分析,大白话带你了解!

本文分享自华为云社区《从前后端的角度分析options预检请求——打破前后端联调的理解障碍》,作者: 砖业洋__ 。

options预检请求是干嘛的?options请求一定会在post请求之前发送吗?前端或者后端开发需要手动干预这个预检请求吗?不用文档定义堆砌名词,从前后端角度单独分析,大白话带你了解!

从前端的角度看options——post请求之前一定会有options请求?信口雌黄!

你是否经常看到这种跨域请求错误?

这是因为服务器不允许跨域请求,这里会深入讲一讲OPTIONS请求。

只有在满足一定条件的跨域请求中,浏览器才会发送OPTIONS请求(预检请求)。这些请求被称为“非简单请求”。反之,如果一个跨域请求被认为是“简单请求”,那么浏览器将不会发送OPTIONS请求。

简单请求需要满足以下条件:

  1. 只使用以下HTTP方法之一:GET、HEAD或POST。
  2. 只使用以下HTTP头部:Accept、Accept-Language、Content-Language、Content-Type。
  3. 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请求。请求满足以下简单请求条件:

  1. 使用POST方法。
  2. 使用的HTTP头部仅包括Content-Type。
  3. 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请求。请求不满足简单请求条件,因为:

  1. 使用了非允许范围内的Content-Type值("application/json" 不属于 application/x-www-form-urlencoded、multipart/form-data或text/plain)。
  2. 使用了一个自定义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请求的返回

从后端的角度看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() {
 }
 @Bean
 public CorsFilter corsFilter() {
 // 1. 添加cors配置信息
 CorsConfiguration config = new CorsConfiguration();
 // Response Headers里面的Access-Control-Allow-Origin: http://localhost:8080
 config.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: true
 config.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, headerusertoken
 config.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. 返回重新定义好的corsSource
 return 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://www.toymoban.com/news/detail-445763.html

到了这里,关于从前后端的角度分析options预检请求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务

    【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务

    这篇文章,主要介绍如何通过Nginx服务器转发客户端的WebSocket接口到后端服务【知识星球】。 目录 一、Nginx配置WebSocket 1.1、Nginx配置内容 1.2、客户端请求地址 1.3、创建WebSocket测试工程 1.4、启动测试 1.5、WebSocket超时问题 1.5.1、设置超时时间 1.5.2、建立心跳机制(推荐) 今天

    2024年04月11日
    浏览(14)
  • 前端请求传输token到后端的两种方式

    谈谈 cookie session jwt - 掘金 前端在每次请求时把 token 放在请求头中发送给后端,目前有两种方式: 一是 通过 cookie 的形式 ,即把 token 放在 cookie 中,每次浏览器会自动帮我们带过去,不需要我们自己设置。 二是 放在请求头 header Authorization 中 ,需要我们自己手动设置请求头

    2024年02月07日
    浏览(16)
  • 使用Python创建websocket服务端并给出不同客户端的请求

    使用Python创建websocket服务端并给出不同客户端的请求

    作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 WebSocket 和HTTP一样,也是一种通讯协议,允许服务端主动向客户端推送数据。 在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据

    2024年01月17日
    浏览(11)
  • 测试大姐提了个bug,为什么你多了个options请求?

    测试大姐提了个bug,为什么你多了个options请求?

    刚准备下班呢,测试大姐又给我提个 bug ,你看我这就操作了一次, network 里咋有两个请求? 我心一惊,”不可能啊!我代码明明就调用一次后端接口,咋可能两个请求!“。打开她的截图一看:多个 options 请求。 我不慌不忙解释道:”这不用管,是浏览器默认发送的一个预

    2024年02月10日
    浏览(11)
  • HTTP 之 options预请求 nginx 解决跨域 postman调试跨域问题

    HTTP 之 options预请求 nginx 解决跨域 postman调试跨域问题

    get:参数在url上,浏览器长度有限制,不安全 post:参数不可见,长度不受限制 put:上传最新内容到指定位置 delete:删除请求的url所表示的资源 head:不返回相应主体,主要用于客户端查看服务器性能 options: 与head类似,是客户端用于查看服务器的性能 。JavaScript的XMLHttpRe

    2024年02月04日
    浏览(43)
  • 主成分分析(PCA)——矩阵角度推导

    主成分分析(PCA)——矩阵角度推导

    最近机器学习课上正式讲了主成分分析,只是老师说的很快,我并没有完全理解。随后我搜了很多关于这方面的讲解来进行理解,仅CSDN上就有很多讲的很好的文章,从协方差矩阵角度进行说明,基本上我也都理解了。但另一方面我发现可以结合我最近学的矩阵分析,从纯矩阵

    2024年03月15日
    浏览(9)
  • 从安全角度分析Angular本地存储

    随着Web应用程序的不断增长,前端开发人员慢慢意识到使用浏览器提供的本地存储技术可以在不使用外部数据库的情况下方便地保存应用程序的数据。Angular作为目前最流行的前端框架之一,也在其API中提供了许多本地存储技术的支持。但是,在使用本地存储时,安全性问题也

    2024年02月13日
    浏览(10)
  • 从西方经济学的角度分析,努力成本

    个人定义:在某种经济周期情况下,达成某种目标所需要花费的时间成本、脑力成本、体力成本,以及生活成本,其中包括量化的经济周期成本,经济周期包括市场容量,人才技术,行业饱和状况,经济总体发展情况等量化指标;在不同阶段,达成相同的目标所需要付出的成

    2024年02月10日
    浏览(20)
  • Python-Python高阶技巧:HTTP协议、静态Web服务器程序开发、循环接收客户端的连接请求

    Python-Python高阶技巧:HTTP协议、静态Web服务器程序开发、循环接收客户端的连接请求

    当前版本号[20231114]。 版本 修改说明 20231114 初版 1.1 网址的概念 网址又称为URL,URL的英文全拼是(Uniform Resoure Locator),表达的意思是 统一资源定位符 ,通俗理解就是网络资源地址。 URL地址:https://www.itcast.com/18/1122/10/E178J2O4000189FH.html 1.2 URL的组成 域名 : IP地址的别名 ,它是用

    2024年02月04日
    浏览(13)
  • 详细分析Java中的Optional类以及应用场景

    详细分析Java中的Optional类以及应用场景

    在实战中学习,灵活运用每个操作类,具体如下: 源码主要如下: 大致含义如下: 这是一个容器对象,可能包含或不包含非空值。如果有值存在,isPresent() 方法将返回 true,而 get() 方法将返回该值。 提供了一些依赖于包含值的存在或缺失的其他方法,例如 orElse()(如果值不

    2024年04月27日
    浏览(18)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包