什么是Web API
使用HTTP协议通过网络调用的API,是软件组织的外部接口。通过访问URI可以与服务器完成信息交互,获取存放在服务器的数据信息
WEB API的重要性不断提升,开发人员需要设计Web API的机会也越来越多,例如:
- 将已发布的Web在线服务数据功能通过API公开
- 构建现代Web应用
- 开发智能手机应用
- 开发社交游戏
- 公司内部多个系统的集成
那么Web API如此重要,如何设计出优美的Web API呢?
- 易与使用
- 便于更改
- 健壮性好
- 不怕公之于众
Web API的设计
URI的设计
方法示例:
方法名 | 说明 |
---|---|
GET | 获取资源 |
POST | 新增资源 |
PUT | 更新已有资源 |
DELETE | 删除资源 |
PATCH | 更新部分资源 |
HEAD | 获取资源元信息 |
用过以用户模块为例子,看下URI设计示例:
目的 | URI | 方法 |
---|---|---|
获取用户信息列表 | http://api.example.com/v1/users | GET |
新用户注册 | http://api.example.com/v1/users | POST |
获取特定用户信息 | http://api.example.com/v1/users/id | GET |
更新用户信息 | http://api.example.com/v1/users/id | PUT |
删除用户信息 | http://api.example.com/v1/users/id | DELETE |
每个URI路径最前面/v1
表示API版本信息,/users
和/users/id
分别表示“用户集合”和“单个用户”,比如ID为1234的用户表示为/users/12345
接下来看下如何设计同好友关系信息的API:
目的 | URI | 方法 |
---|---|---|
获取当前用户好友列表 | http://api.example.com/v1/users/id/friends | GET |
添加好友 | http://api.example.com/v1/users/id/friends | POST |
删除好友 | http://api.example.com/v1/users/id/friends/id | DELETE |
好友信息与特点用户关联,因此获取好友信息可以设计为/users/id/frineds
这样的形式,也就是和单个用户的URI相连,在删除好友时,指定friends后面的ID,用好友的ID更合适,可以形成“自己的用户ID“+“好友的用户ID”
这种唯一形式,表示特点资源
在设计URI时需要注意:
- 使用名词复数形式
- 注意所使用的单词,准确简明易懂
- 不使用空格及需要编码的字符
- 使用连接符来连接多个单词(- or _ or 驼峰法)
如何设计过滤操作,即需要用到查询参数,在URI末尾?后面加一系列的参数
例如使用分页,一般会使用limit
、offset
和per_page
、page
:
per_page=50&page=3
limit=50&offset=100
使用page和offset这类相对位置来获取数据时,随着数据量增加,性能会是很大的问题,因为需要从首条数据开始计数,其次,如果数据更新频率很高,会导致获取当前数据出现偏差,因为用户获取最开始20条数据后,准备获取接下来的20条数据,在这段时间内数据有更新,将导致获取数据与期望的不一致
可以使用绝对位置获取数据,比如某个ID之前或某个日期之前等条件
用户过滤的参数:
- http://api.example.com/v1/users?name=lwyang
- http://api.example.com/v1/users?q=lwyang
第一条可以表示名字限定为lwyang,第二条可以表示全文搜索,检索是否包含lwyang
使用查询参数还是路径?
从设计的角度,凡是可以附加在查询参数里的信息都可以附加在URI路径里,主要决策依据:
- 是否可以表示唯一资源所需信息
- 是否可以省略
资源是否唯一,如通过ID过去所需信息,该信息唯一,将ID放到路径更合适
是否可以省略,如搜索时用到的limit、offset或page等参数,如果省略,多数情况会启用默认值不会出错,所以放到查询参数更合适
响应的设计
不要做不必要的封装,比如在返回数据结构里,用统一结构将所有数据包装起来
返回的JSON数据用了header和response两个域,实际有效数据存放于response中,而header里保存了所有API元数据,这样的便捷性显而易见,但封装显得冗长,并不值得,因为WEB API基本都是用HTTP协议,HTTP已经完成的封装的工作,可以通过返回合适的状态码来帮助用户判断是否发现了某种错误
状态码 | 含义 |
---|---|
1字头 | 消息 |
2字头 | 成功 |
3字头 | 重定向 |
4字头 | 客户端错误 |
5字头 | 服务端错误 |
当请求成功时:
GET
:成功返回200
(“OK”),返回实际数据POST
:成功返回201
(“Created”),并返回发方法所操作的数据DELETE
:成功返回204
(“No Content”)PUT、PATCH
:成功返回200
(“OK”),并返回发方法所操作的数据
当请求出错时:
状态码 | 含义 |
---|---|
400 | Bad Request,其他错误,其他状态码无法描述的错误类型 |
401 | Unauthorized,认证错误,如未登陆 |
403 | Forbidden,没有操作权限 |
404 | Not Found,访问资源不存在 |
405 | Method Not Allowed,方法不被允许 |
406 | Not Acceptable,不支持客户端指定数据格式 |
408 | Request Timeout,超时 |
409 | Confilct |
429 | Too Many Requests,访问次数超出允许范围,限速有关 |
500 | Internal Server Error,服务端自身存在问题 |
503 | Service Unavailable,服务端暂时不可用 |
当出错时,需要返回详细的错误信息,仅通过状态码表示还不够,因此可以自定义code和message,如下放在消息体中: