前言
我们平常开发中,使用最多的还是 HTTP/1.1,因为它是目前最广泛使用的版本。
所以这篇文章我们重点学习 HTTP/1.1 的使用,以及请求和响应的格式。
HTTP 请求格式
一个完整的 HTTP 请求包含四个部分:
- 请求行:第一行
- 请求头:第二行开始的多行
- 空行:头部和实体之间必须有空行
- 请求体(可选):最后一部分
打开浏览器的network面板,点击一个请求,可以看到请求行和请求头:
下面举个简单的例子,来理解下 HTTP/1.1 的请求格式:
POST /api/login HTTP/1.1 // 请求行:方法 路径 协议版本
Host: www.example.com // 请求头开始
Content-Type: application/json // 声明发送的数据格式
Content-Length: 39 // 声明发送的数据长度
User-Agent: Mozilla/5.0 // 浏览器信息
Accept: application/json // 期望返回的数据格式
// 空行
{ // 请求体开始
"username": "zhang",
"password": "123"
}
上面是一个向/api/login 发送一个 POST 请求。请求体是一个 JSON 对象,包含用户名和密码。
请求行包含请求方法、路径和协议版本。请求头包含客户端发送的元数据,如内容类型、长度、用户代理等。空行用于分隔请求头和请求体。请求体包含实际发送的数据。
请求头的格式是:字段名: 字段值,字段名和字段值之间用一个空格分隔。像上面的:
Host: www.example.com
Content-Type: application/json
Content-Length: 39
User-Agent: Mozilla/5.0
Accept: application/json
请求头中有些字段是通用的,也是比较重要的,下面稍微介绍下:
常用请求头
- Host(必需的)
- 指定请求的服务器域名
Host: api.example.com
- Content-Type(发送数据时需要)
- 指定发送的数据格式
Content-Type: application/jsonContent-Type: application/x-www-form-urlencodedContent-Type: multipart/form-data(上传文件时使用)
- Content-Length(发送数据时需要)
- 指定发送数据的长度(字节数)
Content-Length: 39
- Authorization(身份认证时需要)
- 发送身份验证信息
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
- Cookie(需要发送 cookie 时)
- 发送存储在浏览器的 cookie
Cookie: sessionId=abc123; userId=789
- Accept(指定期望的响应格式)
Accept: application/jsonAccept: text/html,application/xml
- User-Agent(浏览器信息)
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
这些除了Content-Type,Authorization,我们需要额外设置,其他都是浏览器自动设置的。
HTTP支持多种请求方法,常用的有GET、POST、PUT、DELETE等。
常见的请求方法
- GET: 获取资源
GET /api/users/1 HTTP/1.1
Host: api.example.com
- POST: 创建资源
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "张三", "age": 18}
- PUT: 更新资源
PUT /api/users/1 HTTP/1.1
Content-Type: application/json
{"name": "张三", "age": 20}
- DELETE: 删除资源
DELETE /api/users/1 HTTP/1.1
Host: api.example.com
下面看个经典的前端fetch发送post请求的代码例子:
fetch('https://api.example.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token666'
},
body: JSON.stringify({ username: 'zhang', password: '123' })
})
指定路径为https://api.example.com/login,请求方法为POST,请求头为Content-Type: application/json和Authorization: Bearer token666,请求体为{ username: 'zhang', password: '123' }。
HTTP 响应格式
HTTP响应是服务器返回给客户端的数据,完全由服务器控制,客户端只能被动接收,无法控制。
HTTP 响应也包含四个部分:
- 状态行:第一行
- 响应头:第二行开始的多行
- 空行:头部和实体之间必须有空行
- 响应体:最后一部分
打开浏览器的network面板,点击一个请求,可以看到状态行和响应头:
下面举个简单的例子,来理解下 HTTP/1.1 的响应格式:
HTTP/1.1 200 OK // 状态行:协议版本 状态码 状态描述
Content-Type: application/json // 响应头开始
Content-Length: 57 // 响应数据的长度
Date: Mon, 23 May 2023 02:21:54 GMT // 响应时间
Server: nginx/1.16.1 // 服务器信息
// 空行
{ // 响应体开始
"code": 0,
"data": {
"token": "xxx666"
}
}
上面是服务器返回的响应,状态码为200,表示请求成功,响应头包含内容类型、长度、日期、服务器信息等。响应体包含实际返回的数据。
读懂响应头的状态码很重要,是我们理解接口成功与否的关键窗口,除了200,常见的还有404、500等。
常见的状态码
- 2xx - 成功
- 200 OK:请求成功
- 201 Created:创建成功
- 204 No Content:删除成功
- 3xx - 重定向
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向
- 304 Not Modified:资源未修改
- 4xx - 客户端错误
- 400 Bad Request:请求格式错误
- 401 Unauthorized:未认证
- 403 Forbidden:无权限
- 404 Not Found:资源不存在
- 5xx - 服务器错误
- 500 Internal Server Error:服务器内部错误
- 502 Bad Gateway:网关错误
- 503 Service Unavailable:服务暂时不可用
响应头的格式
响应头的格式和请求头的格式差不多,都是字段名: 字段值,字段名和字段值之间用一个空格分隔。
响应头中有些字段是通用的,也是比较重要的,下面稍微介绍下:
1. 缓存相关
- Cache-Control: max-age=3600, public 。表示缓存控制
- max-age:缓存时间(秒)
- public:可以被任何缓存区缓存
- private:只能被浏览器缓存
- no-cache:每次都需要向服务器验证
- no-store:不缓存任何内容
- ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4" 表示资源的唯一标识符,用于验证缓存是否有效
- Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT ,表示资源最后修改时间,也用于缓存验证
2. 内容相关
Content-Type: application/json; charset=utf-8 用来
返回内容的类型和编码
常见值:
- text/html:HTML文档
- application/json:JSON数据
- text/plain:纯文本
- image/jpeg:JPEG图片
Content-Length: 348
返回内容的长度(字节数)
Content-Encoding: gzip
内容的编码方式,常用于压缩
- gzip:最常用的压缩方式
- deflate:另一种压缩方式
- br:专为 HTTP 优化的压缩算法
3. 跨域相关
Access-Control-Allow-Origin: *
允许跨域访问的域名
- *:允许任何域名
- example.com:只允许特定域名
Access-Control-Allow-Methods: GET, POST, PUT
允许的 HTTP 方法
Access-Control-Allow-Headers: Content-Type
允许的请求头
Access-Control-Max-Age: 86400
预检请求的有效期(秒)
4. 连接相关
Connection: keep-alive
连接是否保持
- keep-alive:保持连接
- close:关闭连接
Keep-Alive: timeout=5, max=1000
连接保持的参数
- timeout:空闲时间(秒)
- max:最大请求数
提示:
- 不是所有响应都需要包含所有这些头部
- 根据实际需求选择合适的响应头
- 可以通过浏览器开发者工具的 Network 面板查看实际的响应头
下面看一个JS中处理响应头和响应体的例子:
// 发送请求并处理响应
fetch('https://api.example.com/user/1', {
method: 'GET',
headers: {
'Authorization': 'Bearer token666'
}
})
.then(response => {
// 1. 处理响应状态
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 2. 查看响应头信息
console.log('响应状态:', response.status); // 200
console.log('内容类型:', response.headers.get('content-type')); // application/json
console.log('内容长度:', response.headers.get('content-length')); // 348
// 3. 处理响应体
// response.json() 用于 JSON 数据
// response.text() 用于文本数据
// response.blob() 用于二进制数据(如图片)
return response.json();
})
.then(data => {
// 4. 使用响应数据
console.log('用户数据:', data);
})
.catch(error => {
// 5. 处理错误
console.error('请求失败:', error);
});
提示:
- response.ok 为 true 表示状态码在 200-299 之间
- response.headers 是一个 Headers 对象,可以用 get() 方法获取特定头部
- response.json() 返回一个 Promise,需要用 await 或 then 处理
- 错误处理很重要,网络请求可能会失败
总结
本文详细介绍了 HTTP/1.1 协议的请求和响应格式,主要包括以下几个方面:
- HTTP 请求的组成
- 请求行(方法、路径、协议版本)
- 请求头(Host、Content-Type 等)
- 空行
- 请求体(可选)
- HTTP 响应的组成
- 状态行(协议版本、状态码、状态描述)
- 响应头(Content-Type、Cache-Control 等)
- 空行
- 响应体
- 重要的 HTTP 头部
- 缓存相关:Cache-Control、ETag、Last-Modified
- 内容相关:Content-Type、Content-Length
- 跨域相关:Access-Control-Allow-Origin
- 安全相关:Set-Cookie、X-Frame-Options
- 连接相关:Connection、Keep-Alive
- 状态码的分类
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务器错误
- 实际应用
- 如何在前端发送 HTTP 请求
- 如何处理响应状态和响应头
- 如何处理响应数据
- 如何进行错误处理
下篇文章我们来看看实际的前端工程化的项目中,如何请求接口的。这个是大家刚实习进入公司,拿到真实项目,遇到的最大的问题,语法我都会,但是项目中的这种写就很陌生,还要分什么开发环境,线上环境,真是头大。不过没关系,我们一起来看看