从万维网开始的http协议、cookie和session、curl等应用
功能性引入
此处假定读者已具备基本的计算机网络知识,例如osi五层网络通信模型。
因特网通过tcp/ip协议实现了端到端通信的正确性,无论是所谓的三次握手、四次挥手,还是滑动窗口、快重传、快恢复等机制,总之通过他们实现了端到端通信准确性和实时性。而我们所熟知的http协议,全称为超文本传输协议也正是基于tcp/ip协议,他最初的构想实际上是为了方便访问位于服务端的静态网页。
通信步骤如下
1,客户端输入网址
2,服务器返回网页
3,浏览器接受并渲染
但深入到协议层的步骤如下
1,客户端输入网址
2,浏览器和服务器进行tcp三次握手,建立tcp连接
3,浏览器通过tcp发起http报文
4,客户端根据请求报文返回相应信息
5,浏览器接收相应报文,并进行渲染
http报文定义
假定我们已经知道tcp如何保证通信的正确性,那么我们应该知道http报文究竟是什么?于笔者来说,他们过去都是非常抽象的上层概念,例如get、post等请求类型,例如queryString、路径参数、请求体等参数类型,例如restfull。
但是http层面从url到报文究竟是如何表示?
常见的http请求格式
GET /index.html HTTP/1.1
HOST:www.baidu.com
Connection:close
User-Agent:Mozilla/5.0
请求类型 路径 版本
首部字段名:值
空行
请求体
常见的http响应格式
HTTP/1.1 200 Accepted
Content-Length: 651864
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>省略
版本 状态码 状态短语
首部字段名:值
空行
响应体
无论请求还是响应实际上都只分为三部分,请求描述、附加字段、报文的携带数据。
那么了解上述格式的作用是什么?仅仅使用上层封装不是也够用了吗?hhh,从http协议中所衍生出来的sse、websocket等有状态的协议,可都是基于上述格式,他们的本质实际上都是针对于报文解析,也就是所谓协议的真相,例如上述字段中的Content-Length: 651864
,他代表的含义就是报文的携带数据的大小,这对于接收报文非常有用,可以及时停止接收,也可以根据数据大小来判断是否有遗漏的数据包。
此外针对Content-Type常见的场景
值 | 含义与场景 | 备注 |
---|---|---|
text/plain; charset=utf-8 |
纯文本 | charset 表示字符集,文本类常见 |
text/html; charset=utf-8 |
HTML 页面 | 浏览器默认渲染为页面 |
text/markdown; charset=utf-8 |
Markdown(.md)文件 | 浏览器不会原生把 MD 渲染成 HTML;通常当作文本或由前端库/服务端转成 HTML |
cookie和session
针对到http报文层面,众所周知,cookie实际上是真的有这个请求字段被报文在浏览器客户端,用于表示用户的个人身份,但恐怕大多数人都不知道它首先来自服务器端。
现代做法
1,浏览器首次请求web服务器,
2,服务器返回相应报文中携带请求头set-cookie: xxxx
3,客户端接收上述请求头,并在以后的请求都携带上该数据
session虽然一直说是存在服务器端,但同样也需要浏览器端参与,服务器生成sessionId来对应存在与服务器存储的真实用户信息,同样是在初次请求时通过setCookie交给浏览器客户端,然后保存与cookie中,但是注意sessionID并非只能存储与cookie,例如自定义请求头。
curl
curl请求对应http请求
curl -X POST -H "Accept: application/json" --data '{"name":"Alice","age":20}' https://example.com
POST / HTTP/1.1
Host: example.com
Accept: application/json
Content-Type: application/x-www-form-urlencoded ←(见下方“改进建议”)
Content-Length: <自动计算>
{"name":"Alice","age":20}