网络应用程序,分为前端和后端两个部分。
当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…)。因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。
这导致API构架的流行,甚至出现"APIFirst"的设计思想。RESTful API是目前比较成熟的一套互联网应用程序的API设计理论。
¶ REST ful 简介
REST(Representational State Transfer)表述性状态转换
REST指的是一组架构约束条件和原则。 如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。
REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。
¶ 接口风格
遵循RESTful设计风格,同时控制复杂度保持实用性
¶ 遵循原则:
-
使用 HTTPS 协议
-
版本号置入 URL / Header 中
-
只允许返回 json 格式
-
POST / PUT 上使用 json 输入
-
使用 HTTP 状态码作为错误提示
-
Path 尽量使用名词,不使用动词,将每个URL看成一个资源
-
使用 HTTP 动词 (GET、POST、PUT、DELETE) 作为 action 操作 URL资源
-
返回结果
-
GET:返回资源对象
-
POST:返回新生成的资源对象
-
PUT:返回完整的资源对象
-
DELETE:返回一个空文档
-
过滤信息(常见)
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?page=2&per_page=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?animal_type_id=1:指定筛选条件
(参数的设计允许存在冗余,即允许API路径和URL参数偶尔有重复。比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的)
-
速率限制
- X-RateLimit-Limit: 每个IP每个时间窗口最大请求数
- X-RateLimit-Remaining: 当前时间窗口剩余请求数
- X-RateLimit-Reset: 下次更新时间窗口的时间(UNIX时间戳),达到下个时间窗口时,Remaining恢复为Limit
¶ 忽略原则:
- Hypermedia API(HATEOAS),通过接口URL获取接口地址及帮助文档地址信息
- 限制返回值的域,fields=id,subject,customer_name
- 缓存,使用ETag和Last-Modified
¶ 路径
路径又称"终点"(endpoint),表示API的具体网址。
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。
¶ HTTP 动词
对于资源的具体操作类型,由HTTP动词表示。
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
- HEAD:获取资源的元数据。(不常用)
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。(不常用)
下面是一些例子及其解释
- GET /zoos:列出所有动物园
- POST /zoos:新建一个动物园
- GET /zoos/ID:获取某个指定动物园的信息
- PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
- PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
- DELETE /zoos/ID:删除某个动物园
- GET /zoos/ID/animals:列出某个指定动物园的所有动物
- DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
¶ 公共参数
¶ Headers
公共请求参数是指每个接口都可能需要传递的参数,公共参数通过header传递。
参数 | 是否必须 | 说明及Header格式 |
---|---|---|
app | 所有接口必须 | 请求客户端应用标识:-ios、-android、-pc、-h5[ header格式: X-Co-App: $app`] |
user_id | App登录后所有接口都传, Web通过session机制获取 | 用户标识 [ header 格式: Authorization: CoAPI base64(user_id:token) ] |
token | App登录后所有接口都传, Web通过session机制获取 | 授权访问令牌 [ header格式: Authorization: CoAPI base64(user_id:token) ] |
-
Web 应用通过 Cookies 传递 session_id,user_id 和 token 无需传递,接口会从 session 自动获取
-
同一 token 值在APP和Web各应用间通用(token即为session_id)
-
APP 修改 user-agent,在原有 user-agent 尾部添加
%app/$version
和NetType/$value
如:- Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/V7.5.3.0.MXGCNDE) $app-android/3.0.0 NetType/4G
- Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) $app-ios/3.0.0 NetType/WIFI
-
APP 取值及释义样例
APP取值 客户端名称 [域名] admin-pc 管理中心PC网页版 [admin.url.com] admin-h5 管理中心手机网页版 [admin.url.com] admin-ios 管理中心IOS版 admin-android 管理中心Android版
¶ Cookies
- **用于告知服务端是否支持Webp的Cookie:**cookie name是
supportWebp
,取值是1(支持)和0(不支持),未传递时服务端默认取值为0。 - Webview植入Session的Cookie:
¶ 参数传递
遵循RESTful规范,使用了GET, POST, PUT, DELETE共4种请求方法。
- GET:请求资源,返回资源对象
- POST:新建资源,返回新生成的资源对象
- PUT:新建/更新资源,返回完整的资源对象
- DELETE:删除资源,返回body为空
- GET请求不允许有body, 所有参数通过拼接在URL之后传递,所有的请求参数都要进行遵循RFC 3986的URL Encode。
- DELETE删除单个资源时,资源标识通过path传递,批量删除时,通过在body中传递JSON。
- POST, PUT 请求,所有参数通过JSON传递,可选的请求参数,只传有值的,无值的不要传递,contentType为application/json。
4种请求动作中,GET、PUT、DELETE是幂等的;只有POST是非幂等的。幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。 是非幂等是判断接口使用POST还是PUT的决定条件
注意:APP端获取json数据时,对于数值类型字段必须以数值类型转换,无论传递过来的值是否带引号。
¶ 返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范。
- GET /collection:返回资源对象的列表(数组)
- GET /collection/resource:返回单个资源对象
- POST /collection:返回新生成的资源对象
- PUT /collection/resource:返回完整的资源对象
- PATCH /collection/resource:返回完整的资源对象
- DELETE /collection/resource:返回一个空文档
¶ 状态码
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
- 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
- 204 NO CONTENT - [DELETE]:用户删除数据成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
- 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
- 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
- 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
- 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
- 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
不常见的 看这 。
¶ 模块和版本
接口模块相互对立且有版本管理,模块名作为APP配置项进行存储,每个模块的版本号version和endpoint在应用初始化时调用api模块信息接口(通过传递客户端应用名称和版本号获取各个API模块的endpoint和version)获取并存储。
¶ 实例模块及最新版本号
模块 | 模块用途 | 版本号 |
---|---|---|
account | 账户管理 | v1 |
sms | 短信 | v1 |
open | 开发接口(无需参数) | v1 |
¶ 权限
权限分为:
none
:无需任何授权;token
:需要用户登录授权,可通过header Authorization
和Cookie CoSID
传递;admintoken
:需要管理员登录授权,可通过header Authorization
和Cookie CoCPSID
传递;token || admintoken
:用户登录授权或管理员登录授权都可以;sign
: 需要签名,一般用于服务端内部相互调用,详见 API HMAC-SHA1 签名。
建议遵从OAuth 2.0 机制制定权限规则
¶ 速率限制
-
为了防止API被恶意调用,对API调用进行速率限制。
-
速率限制为每IP每15分钟5000次(dev/qa为10W)调用(15分钟是一个时间窗口)。
-
限制是针对所有接口模块一起计算的(Redis key为
APIRL:{IP}
),暂时没有特殊的模块或单个接口(未来可能有)。 -
你可以通过每个接口返回的HTTP headers了解当前速率限制的情况:
- X-RateLimit-Limit: 每个IP每个时间窗口最大请求数
- X-RateLimit-Remaining: 当前时间窗口剩余请求数
- X-RateLimit-Reset: 下次更新时间窗口的时间(UNIX时间戳),达到下个时间窗口时,Remaining恢复为Limit
-
超出速率限制,返回以下错误
1
2
3
4
5HTTP/1.1 429 Too Many Requests
{
"code": "RateLimitExceeded"
"message": 接口调用次数超过限制,请稍后再试
}
¶ 安全注意事项
- 用户登录后用户的token;aliyun OSS的bucket、AccessKey ID与AccessKey secret;微视频的appid、sign、bucket;这些关键数据通过调用接口获得,需要在客户端以安全的方式存储。
- 音频视频在APP内的存储,不允许被拷贝(即使越狱或root后拿走也无法使用)。