Web API的设计与开发¶
Checklist¶
在进行 WebAPI 设计时,下面的检查项需要重点关注。
URI 设计¶
- URI 是否短小且容易输入
- URI 是否能让人一眼看懂
- URI 是否只有小写字母组成
- URI 是否容易修改
- URI 是否反映了服务器端的架构
- URI 规则是否统一
- URI 里用到的单词所表示的意思是否和大部分 API 相同
- URI 里用到的名词是否采用了复数形式
- URI 里有没有空格符及需要编码的字符
- URI 里的单词和单词之间有没有使用连接符
- 有没有在 URI 里嵌入主版本编号,并且能够让人一目了然
HTTP 方法与状态码¶
- 有没有使用合适的 HTTP 方法
- 出错时有没有返回 HTML 数据
- 有没有返回合适的状态码
- 服务器端在维护时有没有返回 503 状态码
响应数据设计¶
- 响应数据格式有没有使用 JSON 作为默认格式
- 响应数据的内容能不能从客户端指定
- 响应数据中是否存在不必要的封装
- 响应数据的结构有没有尽量做到扁平化
- 响应数据有没有用对象来描述,而不是用数组
- 响应数据的名称所选用的单词的意思是否和大部分 API 相同
- 响应数据的名称有没有用尽可能少的单词来描述
- 响应数据的名称由多个单词连接而成时,连接方法在整个 API 里是否一致
- 响应数据的名称有没有使用奇怪的缩写形式
- 响应数据的名称的单复数形式是否和数据内容相一致
- 出错时响应数据里是否包含有助于客户端剖析原因的信息
- 有没有返回合适的媒体类型
安全性¶
- 登录有没有使用 OAuth 2.0
- 有没有使用 HTTPS 来提供 API
- 有没有认真执行 JSON 转义
- 能不能识别 x-Requested-With 首部,让浏览器无法通过 SCRIPT 元素读取 JSON 数据
- 通过浏览器访问的 API 有没有使用 XSRF token
- API 在接受数据时有没有仔细检查非法的参数(负数等)
- 有没有做到即使请求重复发送,数据也不会多次更新
- 有没有在响应消息里添加各种增强安全性的首部
- 有没有实施访问限制
缓存与性能¶
- 有没有返回 Cache-Control, ETag, Last-Modified, Vary 等首部以便客户端用合适的缓存策略
- 不想缓存的数据有没有添加 Cache-Control: no-cache 首部信息
版本管理¶
- 有没有对 API 进行版本管理
- API 版本的命名有没有遵循语义化版本控制规范
- 有没有考虑 API 终止提供时的相关事项
- 有没有在文档里明确注明 API 的最迟提供期限
其他设计考量¶
- 分页的设计是否恰当
- 响应数据的名称有没有使用奇怪的缩写形式
- 必要时能不能支持 CORS
- 对预想的用例标准限定的次数有没有设置得过少
- 是否支持通过查询参数来指定数据格式
- 是否支持不必要的 JSONP
第1章 什么是Web API¶
设计原则¶
- 设计规范明确的内容必须遵守相关规范
- 没有设计规范的内容必须遵守相关事实标准
两类API¶
- LSUD: Large Set of Unknown Developers
- SSKD: Small Set of Known Developers
第2章 端点的设计与请求的形式¶
常见HTTP方法的使用场景¶
- GET : 获取资源
- POST : 创建资源
- DELETE : 删除资源
- PUT : 更新资源(全部信息)
- PATCH : 更新资源(部分信息)
- HEAD : 获取资源(元数据)
常见的端点形式¶
- 蛇形法(Snake Case):
/api/v1/users/profile_image
- 脊柱法(Spinal Case):
/api/v1/users/profile-image
- 驼峰法(Camel Case):
/api/v1/users/ProfileImage
注意:如没有特殊要求,使用蛇形法
第3章 响应数据的设计¶
为什么JSON比XML应用更广泛¶
JSON可以使用更简单的方式来这边雨相同的数据,占用空间更小,并且还能同web默认的客户端语言JavaScript更好地兼容
日期格式¶
优先使用下面的数据格式
- RFC 3339:
2006-01-02T15:04:05+08:00
- Unix时间戳:
1136185445
注意: RFC 3339是ISO 8601的子集
第4章 最大程度地利用HTTP协议规范¶
状态码首位的大概含义¶
状态码 | 含义 |
---|---|
1字头 | 消息 |
2字头 | 成功 |
3字头 | 重定向 |
4字头 | 客户端原因引起的错误 |
5字头 | 服务器端原因引起的错误 |
主要的HTTP状态码¶
状态码 | 名称 | 说明 |
---|---|---|
200 | OK | 请求成功(GET/PUT/PATCH OK) |
201 | Created | 请求成功,新的资源已创建(POST OK) |
202 | Accepted | 请求成功 |
204 | No Content | 没有内容(DELETE OK) |
300 | Multiple Choices | 存在多个资源 |
301 | Moved Permanently | 资源被永久转移 |
302 | Found | 请求的资源被暂时转移 |
303 | See Other | 引用他处 |
304 | Not Modified | 自上一次访问后没有发生更新 |
307 | Temporary Redirect | 请求的资源被暂时转移 |
400 | Bad Request | 请求不正确 |
401 | Unauthorized | 需要认证(我不知道你是谁) |
403 | Forbidden | 禁止访问(我知道你是谁,但你没有执行操作的权限) |
404 | Not Found | 没有找到指定的资源 |
405 | Method Not Allowed | 无法使用指定的方法 |
406 | Not Acceptable | 同Accept相关联的请求部件含有无法处理的内容 |
408 | Request Timeout | 请求在规定时间内没有处理结束 |
409 | Conflict | 资源存在冲突 |
410 | Gone | 指定的资源已不存在 |
413 | Request Entity Too Large | 请求消息体太大 |
414 | Request-URI Too Long | 请求的URI太长 |
415 | Unsupported Media Type | 不支持所指定的媒体类型 |
429 | Too Many Requests | 请求次数过多(限流) |
500 | Internal Server Error | 服务器遇到错误 |
503 | Service Unavailable | 服务器暂时停止运行 |
第5章 开发方便更改设计的Web API¶
如何管理版本号¶
最为常用的还是在URI的路径中嵌入版本信息,并遵循语义化版本控制的规范,使用主版本编号
访问废弃版本号的响应¶
410,表示当前API已经停止对外公开,请使用新版本
第6章 开发牢固的Web API¶
问题分类¶
非法获取服务器端和客户端之间的信息
- 利用HTTPS对HTTP通信实施加密
利用服务器端的漏洞非法获取和篡改信息
- JSON劫持
预设通过浏览器访问的API中问题
- XSS: Cross Site Scripting, 跨站脚本
- XSRF: Cross Site Request Forgery, 跨站请求伪造
安全相关的HTTP头部¶
X-Content-Type-Options: nosniff
, 防止浏览器将JSON数据按照非JSON类型解释X-XSS-Protection: 1; mode=block
, 浏览器可以有效地检测个防御XSS攻击X-Frame-Options: DENY
, 防止浏览器将页面嵌入到框架中Content-Security-Policy: default-src 'self'
, 指定了默认的资源加载策略,即只允许从与当前页面相同的源('self'
)加载资源Strict-Transport-Security: max-age=31536000; includeSubDomains
, 强制浏览器通过 HTTPS 访问网站,从而提高网站的安全性,防止中间人攻击和协议降级攻击
限速相关的HTTP头部¶
X-RateLimit-Limit: 1000
, 在一个单位时间内允许的最大请求数X-RateLimit-Remaining: 999
, 在当前时间窗口内剩余的请求次数X-RateLimit-Reset: 100
, 当前时间窗口结束并重置为新窗口的 Unix 时间戳