首页 > 其他分享 >面试官:post为什么会发送两次请求?

面试官:post为什么会发送两次请求?

时间:2024-09-21 15:24:35浏览次数:1  
标签:面试官 浏览器 请求 预检 发送 服务器 post POST 跨域

面试官:post为什么会发送两次请求? 原创 石杉 石杉的架构笔记  2024年07月29日 09:30 江西 26人听过 之前有人跟我们说,出去面试的时候,有时候会遇到一些让人头疼的问题,比如有一次去字节面试,面试官就问了一个让他很奇怪的问题:“为啥POST请求有时候会发送两次呢?”这个问题听起来挺玄乎的,但其实用大白话来说,原因还挺简单的。咱们这就来聊聊这个事儿。 首先,得明白啥是POST请求。POST请求就是咱们在网上干点啥事儿,比如提交个表单、上传个文件啥的,得跟服务器说:“嘿,我这儿有点东西,你给我处理一下。”这时候,浏览器就会发个POST请求给服务器。 那么,为啥有时候会发两次呢?这其实跟浏览器的“预检”机制有关系。简单来说,就是浏览器在正式发请求之前,会先问问服务器:“嘿,我要发请求了,你准备好了吗?能接收吗?”这个过程就叫做“预检请求”,也叫OPTIONS请求。 为啥要有这个预检呢?因为有时候咱们发的请求可能比较复杂,比如请求头里面带了点特殊的东西,或者请求方法是PUT、DELETE这种不常用的。这时候,浏览器就会有点担心,怕服务器不理解或者不接受这个请求,所以就先发个简单的OPTIONS请求去问问。 如果服务器说:“没问题,你来吧!”那浏览器就会再发一次正式的POST请求。所以,咱们就看到了两次请求:一次是预检的OPTIONS请求,一次是正式的POST请求。 那么,举个实际的例子来说明一下。假设你正在开发一个网页应用,其中有一个功能是让用户能够上传图片。当用户选择了一张图片并点击上传按钮时,浏览器就会发送一个POST请求到服务器,以便将图片上传到服务器上。 但是,如果这个请求中包含了一些特殊的请求头,比如自定义的X-Requested-With头,或者请求的内容类型(Content-Type)不是常见的application/x-www-form-urlencoded、multipart/form-data或text/plain,那么浏览器就会先发送一个OPTIONS请求进行预检。 这个OPTIONS请求会询问服务器是否接受这种类型的请求。如果服务器响应说可以接受,那么浏览器才会继续发送正式的POST请求,将图片上传到服务器上。 预检请求和正式请求之间有一些明显的区别。首先,它们的目的不同。预检请求的目的是询问服务器是否接受某种类型的请求,而正式请求则是实际执行某种操作,比如上传文件、提交表单等。其次,它们的请求方法不同。预检请求总是使用OPTIONS方法,而正式请求则可以使用GET、POST、PUT、DELETE等方法。最后,它们的请求头和请求体也可能不同。预检请求通常只包含一些基本的请求头,而正式请求则可能包含更多的请求头和请求体数据。 所以,先总结一下,POST请求有时候会发送两次,是因为浏览器为了保险起见,先发个预检请求去问问服务器:“我能发这个请求吗?”得到允许后,再发正式的请求。这样,就能确保咱们的请求能够顺利到达服务器,并得到正确的处理了。 好了,现在大家明白了吧,以后面试遇到这个问题就可以很好的回答清楚了,说白了不是发送两次post请求,而是在一些特殊的情况下,如果post请求要带一些特殊的请求头,平时不太常见,浏览器就会发担心服务端没法接收和处理,那如果服务端没法处理,自己何必还发送post请求携带大量的表单数据、文件数据、图片数据过去呢?这不是吃饱了没事干么,对吧! 所以此时才会先发个options预检请求过去,带一些请求头,问一下服务端后面能不能处理正式的请求。另外的话,对于发options预检请求的情况还有一种比较特殊的,就是同源策略下的跨域访问,这个也是有可能会提前发options预检请求的。 浏览器的同源策略,简单来说,就是浏览器为了安全起见,设置的一个规矩。这个规矩规定,来自不同源的网页之间不能直接进行交互。这里的“源”指的是协议(比如http或https)、域名(比如www.example.com)和端口号(比如80或443)这三者的组合。只要这三者中有任何一个不同,就认为是不同的源。 那不同的源肯定不能互相瞎请求啊,比如说浏览器请求服务器A返回了一个网页,结果这个服务器A跑的A系统的网页里,有一个请求要去请求服务器B上部署的B系统,那这种就很奇怪了,对浏览器来说你们是两个服务器,也就是两个不同的系统,干什么要互相瞎访问,有没有可能A系统是一个涉灰系统在搞破坏,盗取数据,对不对? 举个日常的例子,就像你有两个家,一个在北京,一个在上海。虽然都是你的家,但因为地理位置不同(就像协议、域名、端口号不同),所以你不能直接从北京的家跑到上海的家去拿东西,除非你走特殊通道(就像跨域资源共享CORS)。 那CORS的话,全称是跨域资源共享(Cross-Origin Resource Sharing),是浏览器和服务器之间的一种约定,用来解决跨域请求的问题。简单来说,CORS就是一种机制,让服务器告诉浏览器:“嘿,这个网页虽然来自不同的源,但它是安全的,你可以让它访问我的资源。” 就是说服务器A的网页里的JS代码去请求服务器B了,那就是跨域了,那跨域发起的请求就是CORS请求了。 那浏览器发跨域请求的时候,会不回发options预检请求呢?其实也是会的,因为当浏览器发起跨域请求时,并不是所有的请求都会直接发送。有时候,浏览器也是会先发出一个OPTIONS请求,这个请求就像是浏览器在问服务器:“嘿,我这儿有一个网页想发个请求到你的地盘,但是网页和你的话,咱俩不是同一个源的,你得先告诉我,你同不同意?”这个过程就叫做跨域请求之前的预检请求。 那么,跨域请求的时候,什么情况下会发出OPTIONS预检请求呢?主要有以下几种情况: 1、请求方法不是GET、HEAD、POST:因为GET、HEAD、POST这三种方法被认为是“简单”的,通常不会对服务器造成太大影响,所以浏览器会直接发送请求。但如果是PUT、DELETE等方法,浏览器就会先发个OPTIONS请求问问,就怕有人要搞破坏。 对于GET、HEAD、POST这种简单请求,浏览器是没有预检请求的,他会直接发送请求到服务器,并在请求头中包含一个Origin字段,表明这个请求的来源。服务器收到请求后,会根据请求头中的Origin字段来决定是否允许这个跨域请求。如果允许,服务器会在响应头中包含Access-Control-Allow-Origin字段,并返回相应的资源。 但是大部分情况下,很多后端系统如果用的是MVC框架的话,都会默认禁止CORS跨域请求,所以这个时候如果你发现后端系统异常了,配置一下MVC框架,打开CORS跨域请求支持就可以了,那就可以处理跨域请求了。 2、请求头包含了自定义字段:比如你在请求头里加了个X-Token,浏览器就会觉得:“咦,这个请求头看起来不简单,我得先问问服务器同不同意。” 3、Content-Type不是常见的三种类型:常见的Content-Type有application/x-www-form-urlencoded、multipart/form-data和text/plain。如果你用了其他类型,比如application/json,浏览器也会先发个OPTIONS请求。 再总结一下,当浏览器觉得一个跨域请求“不简单”时,就会先发个OPTIONS请求去预检一下,看看服务器同不同意。如果服务器同意了,浏览器才会继续发送正式的请求。这就像你去别人家做客,如果不是很熟,你可能会先打个电话问问对方方不方便,得到同意后再去。 好了,今天咱们从一个面试题问post为什么发两次请求开始引入,用大白话重点聊了聊浏览器的options预检请求问题,并且举了一些例子,尤其是讲了一些同源策略、跨域请求、预检请求之间的关系,相信大家也学到了不少东西,以后面试遇到一定要加油! 阅读 5.0万   ​

标签:面试官,浏览器,请求,预检,发送,服务器,post,POST,跨域
From: https://www.cnblogs.com/cheyunhua/p/18424049

相关文章

  • Nodemailer 概述:在 Nodejs 中轻松发送电子邮件
    nodemailer是一个用于发送电子邮件的node.js模块。这是一个快速概述:transporter:定义电子邮件的发送方式(通过gmail、自定义smtp等)。consttransporter=nodemailer.createtransport({...});登录后复制消息对象:指定电子邮件详细信息,如发件人、收件人、主题和内容(文本/ht......
  • PostgreSQL中的浮点数与实数类型:深入解析与代码实践
    PostgreSQL中的浮点数与实数类型:深入解析与代码实践PostgreSQL作为一款功能强大且灵活的开源关系数据库管理系统,广泛应用于各类复杂的数据存储与查询场景。在PostgreSQL中,处理浮点数与实数类型是一项基本且重要的功能,尤其是在需要进行科学计算、财务分析等高精度数据处理的场合。......
  • PostSync介绍
    PostSync促进技术文章发展介绍这是一个开源的同步文章的软件,你可以使用它来同步你的文章到多个平台。使用打开浏览器,登录各个平台的账号,掘金、CSDN、知乎、公众号、哔哩哔哩、博客园、个人WordPress打开config.yaml文件,配置你的浏览器信息以及浏览器用户数据目录运行命......
  • 面试官问:你如何处理与同事或上级的分歧?【无标题】
    面试官问:你如何处理与同事或上级的分歧?当面试官问你如何处理与同事或上级的分歧,其实面试官的目的是评估你的沟通技巧、冲突解决能力和团队合作的能力。在一起共事,就一定有分歧发生,有争执是正常的,关键是看如何去解决问题。考察的事候选人在面对不同意见时的态度,且能不能有效的......
  • Post Pretraing 技术解析
    一、问题描述在大模型训练中,后预训练技术(Post-pretraining)通常指的是在模型的初始预训练阶段和最终的微调阶段之间进行的一个额外训练步骤。这个步骤的目的是进一步调整模型,使其能够更好地适应特定领域或任务,同时保持或增强其从大规模预训练数据中学到的通用知识和特征表示。......
  • 公众号发送模板消息
    gradle配置plugins{id'java'id'org.springframework.boot'version'3.0.4'id'io.spring.dependency-management'version'1.1.0'}group='com.example'version='0.0.1-SNAPSHO......
  • 从零开始学PostgreSQL (十四):高级功能
    目录1.简介2.视图3.外键4.事务5.窗口函数6.继承7.结论简介PostgreSQL是一个强大且开源的关系型数据库管理系统,以其稳定性、功能丰富性和对SQL标准的广泛支持而闻名。它不仅提供了传统的关系型数据库功能,如事务处理、外键约束和视图,还引入了许多高级特性,如窗口函数、事务和复......
  • SpringBoot拦截器中读取POST请求体参数
    CustomHttpServletRequestWrapper.java:包装请求,缓存请求体数据,重写读取数据方法importjavax.servlet.ReadListener;importjavax.servlet.ServletInputStream;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletRequestWrapper;importj......
  • 面试官:Vue常用的修饰符有哪些有什么应用场景
    一、修饰符是什么在程序世界里,修饰符是用于限定类型以及类型成员的声明的一种符号在Vue中,修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理vue中修饰符分为以下五种:表单修饰符事件修饰符鼠标按键修......
  • 3D高斯渲染 (1-3)ros下 接受c++节点发送的位姿,python节点渲染图像返回,同步版本
    基础学习3D高斯渲染(1-2)ros下接受c++节点发送的位姿,python节点渲染图像返回https://www.cnblogs.com/gooutlook/p/18385485ros自定义消息(图像+标志位+位姿)python和c++发布和接受https://www.cnblogs.com/gooutlook/p/18412553 本工程代码为什么要做这个,因为之前的版本......