HTTP
HTTP版本发展过程
- HTTP0.9是第一个版本的HTTP协议,已过时。它的组成极其简单,只允许客户端发送GET这一种请求,且不支持请求头。HTTP0.9具有典型的无状态性,每个事务独立进行处理,事务结束时就释放这个连接
- HTTP1.0是HTTP协议的第二个版本
- 增加了请求方式POST
- 新增请求头、http状态码等
- 新增cookie
- HTTP1.1
- 新增了keep-alive长连接
- 新增pipeline管道
- 增加了PUT、DELETE、OPTIONS、PATCH等新的方法
- HTTP2.0
- 支持头部压缩、头部支持二进制协议
- 新增多路复用
- HTTP3.0
- http协议的历史性革命性大改版,将底层TCP协议改为UDP,彻底解决队头阻塞问题
- 缺点:兼容性问题,不能大规模使用
陈述HTTP
常见的状态码
-
101:Switching Protocol(协议切换)
- 表示服务器需要使用不同协议来处理客户端的请求
- 场景:比较常见的场景: WebSockets 连接,进行 HTTP 到 WebSockets 的协议切换。
-
200: 客户端请求成功。
-
204:请求收到,但返回信息为空
-
301 Moved Permanently 请求永久重定向。 (永久重定向 浏览器会对301资源进行缓存)
-
302 Moved Temporarily 请求临时重定向。 (临时重定向 不会进行缓存)
比如你的网站从 HTTP 升级到了 HTTPS 了,以前的站点再也不用了,应当返回
301,这个时候浏览器默认会做缓存优化,在第二次访问的时候自动访问重定向的那个地址。而如果只是暂时不可用,那么直接返回
302即可,和301不同的是,浏览器并不会做缓存优化。
-
303:表示服务器要将浏览器重定向到另一个资源
- 这个资源的 URI 会被写在响应 Header 的 Location 字段
-
304 Not Modified 文件未修改,可以直接使用缓存的文件
- 如果客户端发送请求,而请求的内容并没有改变,则服务器应当返回这个状态码,服务器告诉客户端,原来缓冲的文档还可以继续使用。
- POST 请求重定向到 GET 请求
-
400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解。
-
401 Unauthorized 请求未经授权,无法访问。
-
403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因。
-
404 Not Found 请求的资源不存在,比如输入了错误的URL。
-
500 Internal Server Error 服务器发生不可预期的错误,导致无法完成客户端的请求。
-
503 Service Unavailable 服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常。
开发中经常用到的状态码
- 登录成功/注册成功=> 返回200 (服务器成功处理请求) 【强缓存返回200】
- 文件未修改,可以直接使用缓存的文件=>返回304 【协商缓存】
- 用户/邮箱不存在 =>返回 404 (服务器找不到请求页面)
- 服务器错误 => 返回500
- 登录失败/授权失败/用户名或密码不正确 =>返回401 (未授权,需要进行身份认证)
- 201:请求成功并且服务器创建了新的资源
- 422:状态码是指请求格式正确,但是由于含有语义错误,无法响应。
302和301的区别?
参考:https://zhuanlan.zhihu.com/p/267124206
301:永久重定向
- 301重定向会将浏览器访问的旧地址重定向到新地址
- 比如 通过301永久重定向将旧域名重定向至新域名,挽回流量损失和SEO
- 浏览器会对301资源进行缓存
- 可以通过请求头来控制是否缓存,在使用 301 时,我们将其设置为不缓存就可以了。比如设置
Cache-Control: no-store或Cache-Control: no-cache
如何清除 301 重定向缓存?
- 浏览器清除历史记录
- Network 面板清除缓存
- 对某个请求,右键选择Clear Browser Cache 清除浏览器缓存
302:临时重定向
- 请求的资源临时搬到了其他位置
HTTP请求中的Form Data与Request Payload的区别
POST类型的请求会附带请求数据。而常用的两种传参方式为:Form Data 和 Request Payload。
POST请求当参数数量较多,且对数据有一定安全性要求时,会考虑用post请求传递参数数据。POST请求的参数数据是在请求体中。
方式一:Form Data形式 当POST请求的请求头里设置Content-Type: application/x-www-form-urlencoded(默认),
方式二:Request Payload形式
如果使用AJAX原生POST请求,请求头里设置Content-Type:application/json,请求的参数会显示在Request Payload中,参数格式为JSON格式:{"key":"value","key":"value"...},这种方式可读性会更好。
Form Data 和 Request Payload 区别
- 如果请求头里设置Content-Type: application/x-www-form-urlencoded,那么这个请求被认为是表单请求,参数出现在Form Data里,格式为key=value&key=value&key=value...
- 原生的AJAX请求头里设置Content-Type:application/json,或者使用默认的请求头Content-Type:text/plain;参数会显示在Request payload块里提交。
HTTP 缓存的首部字段
参考:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/496
常见的HTTP 缓存首部字段有:
- Expires:响应头,代表该资源的过期时间
- Cache-Control:请求/响应头,缓存控制字段,精确控制缓存策略
- If-Modified-Since:请求头,资源最近修改时间,由浏览器告诉服务器
- Last-Modified:响应头,资源最近修改时间,由服务器告诉浏览器
- Etag:响应头,资源标识,由服务器告诉浏览器
- If-None-Match:请求头,缓存资源标识,由浏览器告诉服务器
其中, 强缓存 :
- Expires(HTTP/1.0)
- Cache-Control(HTTP/1.1)
协商缓存:
- Last-Modified 和 If-Modified-Since(HTTP/1.0)
- ETag 和 If-None-Match(HTTP/1.1)
keep-alive 长连接理解
-
HTTP1.1默认使用了
connection:keep-alive长连接,数据传输完成了保持TCP连接不断开,等待在同域名下继续用这个通道传输数据。如果需要关闭,需要客户端发送Connection:close首部字段 -
提高性能:Keep-Alive机制减少了连接的重复建立和关闭,节约了网络资源和服务器资源
-
连接复用: 当客户端和服务器完成数据传输后,TCP连接并不立即关闭,而是保持打开状态
缺点:
- 资源占用: Keep-Alive连接会占用服务器和客户端的资源
- 连接超时: 如果Keep-Alive连接设置的超时时间过长,可能会导致连接长时间保持打开,浪费资源
Content-type类型
- Content-type: application/json; charset=utf-8
- 将内容指定为JSON格式,以UTF-8字符编码进行编码
application/json和multipart/form-data,默认处理方式UTF-8 ,可以不指定charset=UTF-8
/**
* @description: 常用的contentTyp类型
*/
export enum ContentTypeEnum {
// json
JSON = 'application/json;charset=UTF-8',
// json
TEXT = 'text/plain;charset=UTF-8',
// form-data 一般配合qs
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
// form-data 上传
FORM_DATA = 'multipart/form-data;charset=UTF-8',
}
上传form-data数据
- 当请求的内容类型为Content-type类型为form-data,传递的数据使用formData
const params = new FormData();
params.append('username', this.loginForm.username);
params.append('password', this.loginForm.password);
axios({
method: 'post',
url: 'xx',
data: params,
headers: {
'Content-Type': ContentTypeEnum.FORM_DATA,
},
})
HTTP1
- HTTP 1.x 的文本格式传输
- HTTP1可以开启多个TCP连接
- HTTP1.1默认使用keep-alive(长连接),避免了连接建立和释放的开销
HTTP1的缺点:
-
头部阻塞
- HTTP/1.1 存在头部阻塞(Head-of-Line Blocking)问题,一个请求阻塞可能导致其他请求无法处理,影响性能
-
性能瓶颈
- 在处理大量请求、大文件传输或高并发情况下,性能可能受到限制
-
安全因素
- HTTP1是文本格式传输,且传输的内容都是明文的方式,无法保证数据的安全性
-
性能开销大
- header携带内容过大
-
连接无法复用
- 传输数据时,每次都需要重新建立连接
HTTP2
- HTTP/2引入了“服务端推送(server push)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能。
- 服务器主动推动到数据到客户端缓存中
- HTTP/2提供更多的加密支持
- HTTP/2使用多路技术,允许多个消息在一个连接上传输。
- 只通过一个TCP连接就可以传输多个请求数据
- 解决了浏览器限制同一个域名下的请求数量问题
- 它增加了头压缩(header compression),因此即使非常小的请求,其请求和响应的header都只会占用很小比例的带宽
- 减少了header的大小
- HTTP/2 采用二进制格式传输数据,而非HTTP 1.x 的文本格式
- 二进制协议解析起来更高效
- HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
HTTP3
由于HTTP2使用了多路技术,一个TCP连接可以传输多个请求数据,但是如果这个连接出现了丢包的情况,那么整个TCP都要等待重新传输,也就导致了后面的所有数据都被阻塞了
-
将底层TCP协议改为UDP,彻底解决队头阻塞问题
-
HTTP3最大的改造就是使用了 QUIC协议, 【 QUIC是基于 UDP 协议】
- QUIC(读作“quick”):可以允许多个数据流独立到达
- QUIC与http2的多路复用连接协同工作,允许多个数据流独立到达所有端点,因此不受涉及其他数据流的丢包影响
- 丢包也不会造成阻塞
为什么选择使用UDP协议
参考:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/492
- TCP连接时间长,UDP是无连接
- TCP连接容易丢包
- HTTP/2 使用了多路复用, 一个连接可以传输多个请求数据,但是如果某个连接出现丢包,整个TCP都要等待重新传输
HTTP 1.0/1.1/2.0在并发请求上主要区别是什么?
HTTP/1.0
- 每次TCP连接只能发送⼀个请求,当服务器响应后就会关闭这次连接,下⼀个请求需要再次建 ⽴TCP连接.
HTTP/1.1
- 默认采⽤持续连接 keep alive
- 管道机制:在同⼀个TCP连接⾥,允许多个请求同时发送,增加了并发性
- 默认采⽤持续连接(TCP连接默认不关闭,可以被多个请求复⽤,不⽤声明Connection: keepalive). 增加了管道机制,在同⼀个TCP连接⾥,允许多个请求同时发送,增加了并发性,进⼀步改善 了HTTP协议的效率, 但是同⼀个TCP连接⾥,所有的数据通信是按次序进⾏的。回应慢,会有许多请求排队,造 成”队头堵塞”。
- 简单来说,HTTP 1.1长连接就是一个TCP连接可以允许多个请求同时发送 (并发性),但是这些所有请求都是有次序进行的,就是上一个请求响应后,才能处理下一个请求,会有多个请求排队,容易造成堵塞
如何在http1.0使用持久连接 (支持keep alive)?
- 需要在请求头header中加入Connection:keep-alive
- setRequestHeader("Connection" , "Keep-Alive" / "close") 来控制是否保持连接。
- 由于HTTP1.1默认是持久连接,那如何恢复到HTTP1.0这种状态呢 (服务器响应后关闭连接这种状态)
- 在请求头 Connection字段设置close即可
HTTP/2.0
1.加了双⼯模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了 队头堵塞的问题。
2.使⽤了多路复⽤的技术,做到同⼀个连接并发处理多个请求,⽽且并发请求的数量⽐HTTP1.1 ⼤了好⼏个数量级。
3.增加服务器推送的功能,不经请求服务端主动向客户端发送数据
HTTP/1.1长连接和HTTP/2.0多路复用的区别?
HTTP/1.1:同⼀时间⼀个TCP连接只能处理⼀个请求, 采⽤⼀问⼀答的形式, 上⼀个请求响应后 才能处理下⼀个请求. 由于浏览器最⼤TCP连接数的限制, 所以有了最⼤并发请求数的限制.
HTTP/2.0:同域名下所有通信都在一个连接里完成,消除了因多个 TCP 连接⽽带来的延时和 内存消耗。单个连接上可以并⾏交错的请求和响应,之间互不⼲扰
http的缺点
- 通信使用明文可能会被窃听
- 不验证通信方的身份就可能遭遇伪装
- 无法证明报文的完整性,可能已遭篡改
HTTPS有了解吗
- HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。
HTTPS主要作用是:
(1)对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全;
(2)对网站服务器进行真实身份认证。
为什么不一直使用https?
原因:
- 与http纯文本通信相比,加密通信会消耗服务器的CPU和内存资源,如果每次通信都加密,会消耗相当多的资源
- 因此,一般地,非敏感信息使用http通信,只有包含个人信息等敏感数据时候,才利用https加密通信
- 仅在那些需要信息隐藏时才会加密,来节约资源
- 购买证书的开销也是的原因之一....
网站为什么设置301重定向吗
重定向原因:
(1)网站调整(如改变网页目录结构)
(2)网页被移到一个新地址;
(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。 这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
即使网址更换域名, 通过301永久重定向将旧域名重定向至新域名,挽回流量损失和SEO,优化了SEO
option请求
- OPTIONS方法对服务器发起请求,可以检测服务器支持哪些 HTTP 方法
options请求自动发起
MDN的CORS一文中提到:
浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。
所以这个跨域请求触发了浏览器自动发起OPTIONS请求,看看此次跨域请求具体触发了哪些条件。
总结:
OPTIONS请求即预检请求,可用于检测服务器允许的http方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起OPTIONS请求,即CORS预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求
优化options请求
- OPTIONS预检请求的结果可以被缓存
- Access-Control-Max-Age这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存的最长时间,单位是秒。(MDN)
put、post、 get 、delete
- GET(SELECT):从服务器获取资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源.但实际上两者都可以用来创建或是更新数据.单从技术上来说,他们并没有什么区别.但是在HTTP规范中POST是非等幂的,多次调用会产生不同的结果,比如:创建一个用户,由于网络原因或是其他原因多创建了几次,那么将会有多个用户被创建.而PUT id/456则会创建一个id为456的用户,多次调用还是会创建的结果是一样的,所以PUT是等幂的
区别:
- PUT 这个协议本身不存在验证机制,任何人都可以上传文件,存在安全性问题
- 可通过中间件来验证参数
- delete则可以删除文件,造成恶意攻击
get和post
-
get是取服务器方的数据,post是改服务器方数据。可这么简单理解,在数据库中,get等于select,post等于insert
-
get发送的数据长度有限,则POST的数据可以非常大,没有固定长度
-
get带参数的方式不够优雅,也不够方便
-
get方法的数据通过url传输,post方法的数据可在request body中查到(IE中按F12>Network>Start capturing>双击post请求对应的url,在request body选项栏中查看
-
缓存问题:浏览器不会对post请求做缓存,get请求浏览器可以被缓存
为什么post比get更安全
-
数据传输方式
- GET 请求的数据会暴露在 URL 中,而 POST 请求的数据则包含在请求体中,因此 GET 请求的数据容易被截获和查看,而 POST 请求的数据则相对安全一些
-
请求长度限制
- GET 请求的长度通常受到限制,具体限制由浏览器或服务器设定。这种限制可以防止恶意用户发送过大的请求,但同时也有可能被攻击者利用进行拒绝服务(DoS)攻击。而 POST 请求的长度没有固定限制,理论上可以发送任意长度的数据,这增加了攻击者发送恶意数据的难度
为什么delete和put少人用
-
浏览器的
form表单只支持GET和POST请求,而DELETE和PUT请求并不支持 -
比如公司斥巨资买了一个防火墙,发现只能拦截过滤POST和GET请求
一次完整的HTTP事务是怎样的一个过程?
a. 域名解析
b. 发起TCP的3次握手
c. 建立TCP连接后客户端发起http请求
d. 服务器端响应http请求,浏览器得到html代码
e. 浏览器解析html代码,并请求html代码中的资源
f. 浏览器对页面进行渲染呈现给用户
还用http访问url,不怕被劫持吗?
常见的http劫持有DNS劫持和内容劫持
-
DNS劫持例子:
-
在浏览器输入域名,在DNS域名解析过程中,被黑客劫持到他的私人服务器,结果你的浏览器和黑客的私人服务器建立了连接
-
通过这样的手段,可以获取客户端和服务器之间通信的内容
-
-
内容劫持:
- 通过网站漏洞、服务器漏洞从而拿到网站或者服务器权限
怎么防止网站被劫持?
- 客户端和服务器的数据传输进行加密,是安装ssl证书,将站点从http升级为https
- https协议会对数据传输进行加密
https是如何保证安全的,是如何保证不被中间人攻击的?
加密通信、数字证书验证
-
HTTPS 会在传输数据之前使用密钥对数据进行加密,这样就可以防止中间人攻击
-
密钥的交换和管理会使用密钥协商协议和数字证书来完成
- 密钥协商协议会在客户端和服务器端之间建立一个安全的连接,并且可以在连接中交换密钥
- 数字证书则会认证网站的身份,并且可以防止第三方伪造证书。
-
HTTPS 会在传输数据之后对数据进行校验,这样就可以防止数据在传输过程中被篡改。校验会使用哈希算法(Hash Algorithm)和消息认证码(Message Authentication)
HTTP请求头详解
User-Agent
UserAgent也简称UA
- 通过访问请求可以识别使用的浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识
- 对于设备类型的判断,可以根据 User-Agent 字段中的关键词、正则表达式或者特定标识来进行识别
- 通过解析 User-Agent 字段,服务器可以判断客户端的类型(如 PC 端浏览器、移动设备浏览器等),从而进行适当的处理和响应。
Referer
- Referer 请求头,表示当前页面是通过来源页面的链接进去的,可以告诉服务器该网页时从哪个页面链接过来的
- 服务端一般使用
Referer请求头识别访问来源
场景: 防盗链、防止恶意请求
Cache-Control
指定请求或响应的缓存机制。可以控制缓存的行为,如缓存过期时间、缓存验证等。例如:Cache-Control: max-age=3600, must-revalidate
Accept
指定客户端能够处理的媒体类型(MIME 类型),用于告知服务器可接受的响应内容类型。服务器可以根据该头信息返回适合的响应。例如:Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Host
指定目标服务器的主机名和端口号。作为 HTTP/1.1 规范的一部分,它必须包含在每个请求中,用于确定目标服务器。例如:Host: www.example.com
http请求方法
Get
- 从服务器获取资源
Post
- 向服务器提交数据以进行处理
Put
- 向服务器更新整个资源
Delete
- 从服务器删除资源
Patch
PATCH方法是新引入的,是对PUT方法的补充,用来对已知资源进行局部更新
Options
- 用于确定服务器支持哪些方法以及哪些类型的参数请求