http
协议
HTTP
协议是 Hyper Text Transfer Protocol(超文本传输协议)
的缩写,是用于从万维网( WWW:World Wide Web )
服务器传输超文本到本地浏览器的传送协议。
HTTP
是一个客户端和服务端请求和应答的标准协议,规定了传输报文的指定格式的一种规范协议。
请求和应答(request、response)
,指的是客户端发送HTTP
请求,服务端响应此次的请求,此时就完成了一次HTTP
请求。
符合了 HTTP
协议的规范传输报文,就是 HTTP
协议。
报文
一个完整的 HTTP
协议的报文主要有一下三部分组成:
- 起始行:描述请求/响应的基本信息。
- 首部字段:使用键值对的形式更加详细的说明报文。
- 消息正文:实际传输的数据,可以是文本、文件、音频、视频等数据,比如前端传输的表单,后端响应的
JSON
数据。
请求报文格式如下:
响应报文格式如下:
请求方法
HTTP/1.1
协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源。
下面常见的符合 RESTFul
风格的请求方法:
- GET: 从服务器获取资源
- POST: 在服务器上创建一个新的资源,常用于表单提交,创建数据
- PUT: 更新服务器上的资源,返回整个更新后的资源
- DELETE: 删除服务器上的资源
响应码
下面是常见的 HTTP
响应码:
- 1xx 消息——请求已被服务器接收,继续处理
- 2xx 成功——请求已成功被服务器接收、理解、并接受
- 3xx 重定向——需要后续操作才能完成这一请求
- 4xx 请求错误——请求含有词法错误或者无法被执行,客户端
- 5xx 服务器错误——服务器在处理某个正确请求时发生错误,500
200 | OK | 从客户端发送的请求,服务端已经正常处理了。 |
---|---|---|
204 | No Content | 服务端已经正常处理了,但是响应中没有实体,也不允许有实体。 |
301 | Moved Permanently | 永久性,重定向。表示请求的资源已经拥有了新的 uri,需要重新访问。 |
302 | Moved Temporarily | 临时重定向。 |
400 | Bad Request | 请求报文中存在语法错去。 |
401 | Unauthorized | 请求需要有通过 HTTP 请求的认证信息。 |
403 | Forbidden | 请求被阻止,可能因为某些权限问题,比如访问的文件没有权限等。 |
404 | Not Found | 表示在服务器上没有你要找的资源 |
500 | Internal server Error | 服务器执行程序出现异常 |
首部字段
首部字段是构成 http 报文的重要元素,它能起到传递额外重要信息的作用,首部信息一般会提供报文类型、编码和大小、认证信息,缓存策略等信息。
记住常用的几个即可请求:
- Content-Type:请求体是什么编码格式
- Content-Length:请求体体积大小
- Keep-Alive:保持 tcp 时长
- Accept-Encoding:客户端支持的文件压缩格式
- Accept:支持返回的文件格式
- User-Agent:代理客户端的信息,也就是浏览器的信息响应:
- Content-Type:响应体的数据类型
- Access-Control-Allow-Origin:是否允许跨域
- Keep-Alive:保持 tcp 连接的时长
数据传输
客户端和服务端通过 HTTP
通信,客户端发送数据给服务端时,按照数据位置的不同分为两种:
URI
请求:参数由URL
路径携带传输,分为查询参数(query)和路径参数(param)body
请求体:参数由body
请求体携带,有多种不同的数据格式,格式由报文的字段Content-Type
决定数据的格式form-data
:Content-Type:multipart/form-data
,由body
请求体携带传输,服务端使用body
去获取。x-www-form-urlencoded
:Content-Type:application/x-www-form-urlencoded
,由body
请求体携带传输,所有的方法都能获取。json
:Content-Type:application/json
,传输标准的JSON
格式数据,由body
请求体携带,所有的方法都能获取。
有的开发人员通过请求方式去区分,Get
请求不能接收 body
请求体参数,这种区分显然是不准确的,因为 Get
请求也是有请求体的。
但是在开发过程中,不建议使用 Get
请求去接收请求体参数,因为很多框架在传参时,会特意忽略这一部分的内容,比如在前端的请求库 axios
就会丢弃 Get
请求的 body
参数,所以尽量不要在 Get
请求中发送 body
参数。
TIP
在前端的请求库 axios
中,如果使用 Get
请求,但是把参数放在了请求体中,axios
并不会把参数放入其中。
案例演示
以下案例使用express
演示
query
键值对形式的数据,多个键值对以 &
分隔,填充在 URL
路径的后面URL?key1=val&key2=val
。
app.get('/query', (req, res) => {
console.log(req.query)
res.send('query')
})
param
动态参数,通过 /:param
声明,填充在 URL
的后面URL/:id
。
app.get('/param/:id', (req, res) => {
console.log(req.params)
})
body: form-urlencoded
键和值编码为键值元组,以 '&'
分隔
app.get('/urlencoded', (req, res) => {
console.log(req.body)
})
app.post('/urlencoded', (req, res) => {
console.log(req.body)
})
body: json
app.post('/json', (req, res) => {
console.log(req.body)
})
body: form-data
这个类型的参数,一般是用于文件传输。在 express
需要开启 form-data
解析的插件,才能读取到参数。
开启插件解析,upload
作为保存下载文件的中间件方法。
const express = require("express");
const bodyParser = require("body-parser");
const multer = require("multer");
const upload = multer({ dest: "uploadFiles/" });
const app = express();
// 读取json配置
app.use(bodyParser.json({ limit: "1mb" }));
app.use(
bodyParser.urlencoded({
extended: true,
})
);
// ...
app.listen(3500, () => {
console.log("服务启动端口3500");
});
接收参数
app.post('/form-data', upload.single('cover'), (req, res) => {
// req.file 记录了文件上传的信息
// req.body 记录了其它普通参数(非文件)的信息
console.log(req.file)
console.log(req.body)
})
RESTFul 接口规范
RESTFul
全称:Representational State Transfer => REST
直译为:资源表示层状态转移
REST
是 web
服务的一种架构风格,一种设计风格,而不是一种技术手段,写代码,通常规范大于约束。
只要符合以下这些特点,就可以被称为 RESTFul
风格api
。
版本号
在请求路径上表明请求资源的版本,能有效解决因为升级系统接口不兼容的问题,通常会在
URL
中保留旧版本,同时兼容新的版本比如:
【GET】/v1/user
、【GET】/v2/user
资源路径
请求路径会被视为服务器的一种资源,在请求路径
URL
中,规定只能包含名词,通过请求方式区分请求的动作,多个单词的情况下,需要使用下划线_
划分。比如:
【POST】/v1/user
新增用户请求方式
通过请求方式区分此次请求的动机,动作可以划分为四个大类
C R U D
,对应增查改查
- 【GET】:从服务器上获取资源
- 【POST】:在服务器创建新的资源
- 【PUT】:修改服务器上的资源,并返回整个修改后的资源
- 【DELETE】:删除服务器上的资源
查询参数
接口应该要接收参数,过滤返回的结果
比如分页:
【GET】/v1/api/user?page={num}&size={num}
状态码
使用合适的状态码,常规的业务错误(表单校验不过)不应该直接抛错返回客户端,应该在接口结果中,返回状态码 200,并且返回描述的错误类型,返回业务状态码。如果非业务错误,可直接响应错误给客户端。
常见非业务错误状态码:
- 200,正常返回
- 204,已接收处理,但无实体返回
- 401,未登录用户
- 403,未授权的资源
- 404,找不到资源路径
- 500,服务器代码异常
- 503,服务器错误
响应规范
接口应返回封装统一的
JSON
格式的响应体,成功返回正常数据,失败根据是否为业务错误返回状态码、错误信息、错误标识等比如:
成功返回:
{code: xxx}
业务错误:
{message:'xxxxx',failed:true}
非业务错误:
{statusCode:404,message:'Not Found'}