HTTP
请求报文的构成
1 | (GET/POST..) (/index) HTTP/1.1 |
例如
1 | GET /blogart HTTP/1.1 |
HTTP的请求响应方法
GET
指定服务器并发送请求,一般返回文本内容
POST
向服务器发送数据,服务器返回处理结果
PUT
上传文本内容,类似 FTP 协议上传文件,但是不太安全,一般不使用
HEAD
用来获取服务器的头部相关信息、资源更新时间等,服务器只返回头部信息,不返回主体内容
DELETE
用来请求服务器删除某项资源
OPTIONS
用来查询服务器支持哪些方法
OPTIONS \* HTTP/1.1
HOST: tzwlink.xyz
//响应
HTTP/1.1 200 OK
Allow: GET,POST,PUT,HEAD
CONNECT
使用隧道连接,比如 SSL 安全套层
持久连接和Cookie
原始问题
原本的 http 中,一旦传输完成报文主体,那么 tcp 就断了,但是如果 html 文档里还有图片、数据也需要请求时,还要在建立 tcp 连接再次请求。这样的话太浪费,我们完全可以让 tcp 继续连接,把文档中需要请求的地方请求完,然后如果一段时间都没请求时在断开。
所以引入了 Content: keep-alive,要求就是只要任何一方不提出断开,那么就一直连接
管线化
以往,请求需要得到回应后才能继续下一条请求,这样其实一点也不高效。因为服务器端是可以同时处理大量请求的。
管线化技术实现了可以同时发送多个请求,然后依次响应,无需等待每一次的响应结束。这样一来 web 页面效率大大提高
使用 Cookie 进行状态管理
以往的 http 传输完成后并不会保存信息,通过 Cookie 会在初次请求之后保存部分信息(比如用户登录信息),然后再次请求时可以将 Cookie 加入请求报文中
报文信息
报文格式
前面大概讲过
例子
编码传输
某些时候文件内容较多可以采用编码压缩的方式,但是解压时会增大服务器负担
- gzip
- compress
分块传输
当文件较大时,可以分割为多个部分分时传送,让浏览器一块一块的显示页面
获取部分内容 “获取部分内容”)获取部分内容
当某个内容下载到一半失败时,重新下载往往从头开始,所以引入可以指定范围,比如重新加载时可以从后面一半开始。返回成功状态码 206
GET /great.png HTTP/1.1
HOST: www.tzwlink.xyz
Range: bytes = 5000\-10000
//响应
HTTP/1.1 200 OK
Date: Tue, 10 Jul 2020 15:37:34 GMT
Content-Range: bytes 5000\-10000/10000
Content-Length: 5000
Content-Type: image/jpeg
常见状态码
2XX
- 200 表示成功处理请求,并且返回了响应报文内容
- 204 表示成功处理请求,但是并没有什么资源可以返回,利用这个可以做一些数据修改,添加数据的请求
- 206 表示成功处理部分内容的请求,返回请求所指定的报文内容
3XX
- 301 永久重定向,将请求的 URI 资源永久重定向到某个指定资源位置
- 302 临时重定向,可能重定向的资源还会再次改变
- 303 上面两种状态码明文上规定重定向时不允许改变请求方法,但是实际使用时大家都不怎么遵守,所以增加 303 表示允许重定向时修改请求方法
- 304 允许在特定条件下从缓存获取资源,因为如果重复的请求都要依靠服务端查询那么工作量太大,所以可以从缓存中获取,无需再从数据库查询
比如某个页面初次打开返回 200 OK ,因为第一次需要的数据需要服务端查询数据库生成,这时客服端会在缓存文件中保存 Last Modified;在相同的第二次请求发生时,客服端会在请求中加入 If Modified Since,服务端收到后会根据更新时间判断是该重新查询?返回 200,还是就让客服端用之前的缓存?返回 304
动态页面一般不会保存这些信息,所以不主动添加的话那么每次请求都是 200,如果要做缓存加速就需要添加 Last Modified
- 307 禁止 POST 变成 GET
4XX
- 400 请求报文出现语法错误,服务端无法解析请求,但是浏览器会像对待 200 那样对待这个状态码
- 401 请求认证,在请求资源之前需要认证,需要包含 Authorization 请求证书信息,一般像远程连接数据库就会有这个
- 403 拒绝请求,服务端可以无理由拒绝对指定资源的请求
- 404 服务端找不到指定资源
5XX
- 500 服务端内部程序出现 bug,运行错误
- 503 服务端关闭服务维护了,请求超时
HTTPS
https-http-加密-认证-完整性保护 “https=http+加密+认证+完整性保护”)https=http+加密+认证+完整性保护
原始的http协议内容都是以明文发送,容易被盗取,并且通信时无法确认收到的信息是否完整,或者被篡改。也不知道通信双方是否真实;由此引入 https,事实上是在 http 上做了一些处理。
通过与 SSL 层合用,达到安全通信的效果。SSL 会先建立安全隧道才会通信的
- 确认通信双方身份 : 通过证书认证*来确认双方身份的真实性
- 加密处理 : 由发送方按照一定规则对 http 报文进行加密发送
- 完整性验证 : 例如通过 MD5 和 SHA-1 散列值检验完整性
https 在 tcp 建立的基础上,还需要建立 SSL 连接,之后进行普通的经过加密的 http 请求
加密解密都需要秘钥,一般发送方使用对方提供的公共秘钥进行加密。接受方接受到了之后又使用自己的私有密钥进行解密
通信过程 “通信过程”)通信过程
- 客户端发送打招呼报文 client Hello给服务器,里面包含了 ssl 版本,加密组件等等信息,告诉服务端要干什么。
- 服务端收到了客户端打的招呼,就已 Server Hello 报文进行回复,告诉客服端服务器可以进行 ssl 通信。
- 紧接着服务端把自己的公开密钥证书发给客服端,客服端对发送的信息要依此进行加密,该报文叫做 Certificate 报文。
- 服务端还会在发一条报文 Server Hello Done,告诉客服端第一次握手(协商)结束,确认了需要用的密钥。
- 之后客服端作为回应发送 Client Key Exchange 报文,并且还发送了名为 Pre-master secret 的随机密码串。当然这条信息已经经过第三步的加密处理。
- 客户端又继续发送 Change Cipher Spec 报文,告诉服务端从这里开始以后我发送报文就要按照刚刚的 Pre-master secret 随机密码串进行加密。当然这之前还是按照第三步服务端给的密钥加密。
- 客服端最后发送 Finshed 报文表示结束。
- 服务端必须正确解析上一步客服端发送的 Finshed 报文,因为里面包含了从连接开始到这一步之前所有报文的整体校验值,如果服务端成功解析说明密钥交换成功,服务端就会发送 Change Cipher Spec 报文
- 最后服务端也发送 Finshed 报文表示整个 ssl 连接成功可以进行 http 加密通信了
- 断开连接时客服端会发送 close_notify 报文表示断开。在这后 tcp 连接也断开。
图片来自图解HTTP