你需要知道的 HTTP 协议

小麦2024年08月09日1757 字

HTTP 协议是连接世界的桥梁,

也是人们打开互联网大门的钥匙,

它对于前端的重要性是毫无疑问的。

由于 HTTP 协议内容众多,几分钟视频无法尽善尽美。因此,本期视频只介绍 HTTP 协议中最为重要的部分,以及它在大型客户端应用中的变体。

HTTP 的全称是超文本传输协议,

超文本意味着它不仅仅可以传递文本内容,还可以传递图片、视频等其他形式的数据。

虽然它叫传输协议,但它实际上工作在 TCP/IP 协议栈的应用层,

底层的数据传输由 TCP 或 UDP 负责。

HTTP 协议发展至今已有多个版本,其中最常用的是 HTTP/1.1、HTTP/2 和 HTTP/3。

目前 HTTP/1.1 依然被广泛使用,

HTTP/2 引入了多路复用、二进制帧层、头部压缩等特性,提升了不少传输性能,

HTTP/3 基于 QUIC 协议使用 UDP 作为传输层,进一步降低了连接延迟和提升了传输性能。

值得注意的是,HTTPS 是 HTTP 的加密安全版本,

它在原始 HTTP 协议的基础上加盖了一层 SSL/TLS 来实现加密传输。除了 HTTP/3,TLS 在其他版本中并不是强制要求的。

可以看到,每一代协议升级,都是围绕性能和安全性展开的。

HTTP 协议大体上是一种问答形式,客户端发出请求,服务器处理请求,然后再给出响应。无论是 HTML 文档,还是图片、视频等资源都是通过这种问答来传输的。

服务器会根据不同场景返回不同的响应码,具体可以参照这张表格。

只需要记住 2 开头表示成功处理,

3 开头表示重定向,

4 开头表示客户端错误,

5 开头表示服务端错误。

在请求和响应报文中,除了请求方法和响应码外,最值得关注的就是请求头和响应头

比如:

用于请求上下文的 Host、Referer、User-Agent。

用于响应上下文的 Allow、Server。

用于缓存的 Cache-Control、Last-Modified/Last-Modified-Since 和 ETag/If-NoneMatch。

用于 Cookie 的 Cookie 和 Set-Cookie。

用于安全的 X-Frame-Options、Strict-Transport-Security(HSTS) 和 Content-Security-Policy(CSP)等。

用于跨域控制(CORS)的 Origin 和 Access-Control-* 一套。

用于描述消息主体的 Content-* 一套。

浏览器加载资源会使用 HTTP 协议,前端与服务端的异步请求通常也通过 HTTP 协议完成。

最早我们会通过 XMLHttpRequest(XHR)在浏览器中发起一个异步请求,

后来许多三方库基于它做了功能扩展,比如:jQuery.ajax、superagent 和 axios 等。

直到出现了新的 Fetch 标准,虽然 API 都长得一样,但 Fetch 标准在不同环境下有不同的实现。

比如 Node.js 环境下的 fetch 是基于 Undici 实现的,而在边缘运行时(Edge Runtime)中,Fetch API 也会依据平台有所不同。

因此,在现代前端,应尽可能使用 Fetch API 或其封装库来管理异步请求。

下面使用 Fetch API 和 Node.js 原生 http 模块,举例说明 Content-Type 是如何工作的。

请求代码和报文是这样的,

对应的服务端处理代码和响应报文是这样的。

需要注意的是,请求头和响应头中的 Content-Type 表示消息主体的数据类型,它可以是 JSON、Form、也可以是其他任何 MIME 类型,不同的类型就要有不同的处理程序。

在这个例子中,客户端发送了一段 JSON 类型的数据,服务端应通过 JSON.parse 处理。然后响应了一段纯文本类型,客户端应通过 text() 方法处理它。

这是一个在实际工作中相当容易犯错的问题,前端使用第三方库时默认为 JSON 请求,而服务端默认以 Form 处理时,会百思不得其解为什么我处理不了你的请求,原因就是没理解 Content-Type 的含义。

在不同的场景和环境下,调试 HTTP 有不同的方法。最常见的当然是使用浏览器开发者工具,比如在 Chrome DevTools 的 Network 选项卡下,可以看到非常详细的 HTTP 请求和响应信息。

有时候只想快速看看服务端的响应情况,则可以通过 cURL 等命令行工具完成。

在针对 API 测试的场景下,可以通过 Postman 等自动化工具来批量测试。

而要调试移动设备内的 HTTPS,则需要安装信任证书以及通过网络代理工具来实现。

对于远程或是生产环境,则更多是通过抓包和分析服务端日志来完成。

HTTP 的功能很强大,它足够满足大多数应用场景。但在大型客户端应用中,为了更高效和安全地传输数据,同时兼容 HTTP 协议,会有一些变化。

我们应该知道,不是所有的客户端环境都支持先进的 HTTP/2 或 HTTP/3,

原始 HTTP 协议在更复杂的高并发场景下,会不够高效和稳定。

因此,大型技术基建通常会设计一层无线网关(Gateway),并对 HTTP 协议进行定制,增加登录验证、请求跟踪、监控、限流等功能。

而前端代码通过远程过程调用(RPC)的方式,而非直接使用原始 HTTP。

以 Bilibili 客户端为例,前端发起一个 grpc 请求至 gateway 网关,同时发送了多个自定义请求头,比如:x-bili-mid 表示当前用户、x-bili-trace-id 用于链路日志跟踪、x-bili-device-bin 表示设备信息等等。

在服务端的响应头中,Content-Type 表示这是一个 grpc 响应,x-bili-trace-id 用于日志跟踪等。

可以看到,相比浏览器中的 HTTP,在客户端中的 HTTP 会更复杂,定制化的 HTTP 协议能带来更强大的功能。

本期内容只是简要介绍了 HTTP 协议本身,更多内容我们会在之后的视频中一一展开。如果这期视频对你有帮助,记得点个赞,我是小麦,我们下期不见不散。

评论

你需要先登录才能发表评论
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有