跨域HTTP预检请求、嗅探请求、options请求的解决优化办法
前言:这篇文章没有涉及到基础的协议内容,大部分是开发中会遇到的一些问题。鉴于最近开发遇到一些问题,解决了感到很兴奋,也解决了我去年开发中自己遗留下的疑惑。偷得浮生半日闲,我写这篇文章,目的是为了方便大家理解理论与实际开发中的场景,更快地定位问题,解决开发中遇到的一些问题。
一、什么是HTTP协议
叫做超文本传输协议,他基于TCP/IP协议基础上做传输(知道这个概念就可以)。可以看下我之前在网上看过一张很经典的图:
可以简单理解为:在 发送端 和 接收端 之间的这个超文本解析方式协议就是HTTP协议
为了通俗易懂我这里把他拆出来,先在linux上面讲解。因为不管是浏览器还是linux传输这个都是依据http协议。
1、首先通过linux的 curl 命令来请求接口:
curl -v https://blog.csdn.net/phoenix/web/v1/comment/template/List
如上图所示:任何请求都会有我上面表明的这几个内容。
那么linux是怎么知道哪个是响应头,哪个是响应内容呢,就是根据换行符来决定的。仔细看上面的请求部分、响应头、响应内容,都有个换行,linux就是根据这个识别的,那么可以推测浏览器也可能是根据这个来识别。当然浏览器展示的更直观。
二、请求中为什么会遇到跨域请求
首先要明确一点的是,跨域请求实际上是浏览器进行拦截的。(浏览器的安全策略拦截)你通过linux的curl去请求接口是怎么也不会遇到跨域。所以跨域实际出现一般都是前后端分离场景。
1、什么是跨域请求,就是同一资源,请求别的域资源。简而言之域不同:包括3种情况。
有的人会有疑问是什么域?看下面截图,就是浏览器url地址和请求的url。只要这两个地址有以下任何一个不同就会出现跨域
- 协议不同,http协议 和 https协议
- 端口不同,(截图所示就是端口不同,url上面的默认端口为80,请求地址的为7179,所以这里跨域了)
- 域名(ip)不同,www.baidu.com 和 www.a.com (包括ip和域名,若一个是ip一个域名也会跨域,即使该域名指向该ip)
三、跨域如何解决
一般常用有两种种:前端nginx、后端设置cros允许跨域。(完全够用)
开发中可以在项目中设置proxy代理。通过特定标识符号,例如 /api 来进行代理。
解决跨域比较简单,这里不详细说明。但是有时候会遇到比较特殊的情况,可以看下这篇文章:
https://blog.csdn.net/weixin_40910372/article/details/100068498
四、为什么每次会有options请求
options(预检/嗅探请求)可能会导致请求变慢,每次进行接口请求时候,浏览器会先发出一个options请求,然后才发起正式的请求。
那么为什么会有options请求呢,导致它的原因是:在cros跨域请求下浏览器将请求分为两种:1、简单请求,2、非简单请求(复杂请求),在非简单请求下,就会有options请求。
简单请求:(属于以下几点的就是简单请求,其他的都是非简单请求)
- 请求方式有且只限于:GET、POST、 HEAD
- 请求头不超出以下字段(且没有其他自定义字段):
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
解决办法(优化):可以通过设置响应头部的 Access-Control-Max-Age 来设置预检请求有效期,即在设置的时间内只有第一次会发送出数据,下次这个接口请求(相同接口&相同参数时)不会再发出这个预检请求,而是发送真请求。
方法1、通过nginx添加响应头
location /test/ { add_header ‘Access-Control-Max-Age’ 600; proxy_pass http://a**********/; }
方法2、后端直接设置这个响应头并设置时间
注意:在Chrome浏览器在debug状态,或者勾选上Disable cache,这个配置将失效。