概述
接口形式主要为 RESTful,但又不拘泥于 RESTful。
一个完整的 API 请求过程包括:
- HTTP请求方式
- URL Endpoint
- 请求数据
- 响应结果
下面分述之。
HTTP请求方式
| HTTP Operation | Similar to SQL Stmt | Description | 
|---|---|---|
| GET | SELECT | 获取,查找 | 
| POST | CREATE | 新增创建 | 
| PUT | UPDATE | 在服务器更新资源(客户端提供改变后的完整资源) | 
| PATCH | UPDATE | 在服务器部分更新资源(客户端提供改变的属性) | 
| DELETE | UPDATE | 删除 | 
URL Endpoint
URI指向的是唯一的资源对象/资源集合列表。
统一所有的 endpoint 使用复数使得 URL 更加规整,让API使用者更加容易理解,对开发者来说也更容易实现。
URL Endpoint 组成
一个完整的 URL Endpoint 依次是:
- 网络协议(HTTP, HTTPS)
- 服务器地址
- 版本
- 接口名称
- 参数(可选)- GET 参数使用Query String 格式:如:查询时,过滤条件使用 Query String,如 ?offset=0&limit=10&sort=_created_at;参数列表应该被 encode 过
- 用来描述数据或者请求的元数据放Header中,例如 X-Result-Fields
 
- GET 参数使用Query String 格式:如:查询时,过滤条件使用 Query String,如 
示例:
GET https://api.example.com/v1/users/123456/profiles
说明:
- API 与用户的通信协议,总是使用 HTTPS 协议。
- 尽量将API部署在专用域名之下:api.example.com
- 不使用大写字母;使用中线 -代替下划线_
- 版本控制的另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观
- 一些常见的参数。- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?page=2&per_page=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?user_type_id=1:指定筛选条件
 
接口分类
分为对资源对象的CURD操作,服务型接口和系统设置三种。
资源对象的CURD操作
GET https://~/$version/trades            获取trades列表  
GET https://~/$version/trades/:id        根据id获取单个trade  
POST https://~/$version/trades           创建trade  
PUT https://~/$version/trades/:id        根据id更新trade  
PATCH https://~/$version/trades/:id      根据id部分更新trade  
DELETE https://~/$version/trades/:id     根据id删除trade  
服务型接口
使用 services 标识:
https://~/services/$version/server-name  
示例:
GET https://~/services/$version/search?q=filter?category=file  搜索
PUT https://~/services/$version/queued/jobs                    往任务队列里面添加一个新的任务  
DELETE https://~/services/$version/queued/jobs/:id             根据id删除任务
系统设置
使用 settings 标识:
https://~/settings/$version/server-name  
如:更改界面语言环境
PUT https://~/settings/$version/gui/lang  
{  
    "lang": "zh-CN"  
}
请求数据
使用 JSON 格式传输数据,在 http 请求头和响应头申明 Content-Type:
Request
  Accept: application/json
  Content-Type: application/json;charset=UTF-8
{
  "name": "user1",
  "location": "Xiamen"
}
响应
不使用 Envelope: 响应状态(成功/出错)包含在响应头中;返回的数据结构尽可能简单,不过于包装。
成功时格式
Response
  Content-Type: application/json;charset=UTF-8
{
  "id": 101
  "name" : "user1",
  "location" : "Xiamen"
}
出错时处理
出错响应包括
- 返回的错误信息
- 状态码
 两部分。
自定义异常和异常处理
所有自定义异常继承 RuntimeException, 在业务层抛出, 在统一的 ExceptionHandler 中进行处理。
错误返回数据格式
错误信息格式:
{
    "message": "<Prompt Title; required>",
    "errors": [
        {
            "code": "<error code; required>",
            "description": "<Prompt Message; required>",
            "resource": "<optional>",
            "field":"<optional>",
            "document": "<optional>"
        }
    ]
}
其中:
- 错误标题 message, 必填
- 错误代码 errors.code, 必填
- 错误展示信息 errors.description, 必填
- 资源 errors.resource, 可选
- 属性 errors.field, 可选
- 文档地址 errors.document, 可选
示例: 调用频率超过限制的 Response:
Headers:
    Content-Type: application/json;charset=UTF-8
    X-RateLimit-Limit: 3000
    X-RateLimit-Reset: 1403162176516
    X-RateLimit-Remaining: 0
{
    "message": "Something bad happened :-(",
    "errors": [
        {
            "code": "rate_limit_exceeded",
            "description": "Too Many Requests. API rate limit exceeded",
            "document": "https://developer.github.com/v3/gists/"
        }
    ]
}
应用状态码
| Code | HTTP Operation | Body Contents | Description | 
|---|---|---|---|
| 200 | GET,PUT | 资源 | 操作成功 | 
| 201 | POST | 资源,元数据 | 对象创建成功 | 
| 202 | POST,PUT,DELETE,PATCH | N/A | 请求已经被接受 | 
| 204 | DELETE,PUT,PATCH | N/A | 操作已经执行成功,但是没有返回数据 | 
| 301 | GET | link | 资源已被移除 | 
| 303 | GET | link | 重定向 | 
| 304 | GET | N/A | 资源没有被修改 | 
| 400 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 参数列表错误(缺少,格式不匹配) | 
| 401 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 未授权 | 
| 403 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 访问受限,授权过期 | 
| 404 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 资源,服务未找到 | 
| 405 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 不允许的http方法 | 
| 409 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 资源冲突,或者资源被锁定 | 
| 415 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 不支持的数据(媒体)类型 | 
| 429 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 请求过多被限制 | 
| 500 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 系统内部错误 | 
| 501 | GET,PSOT,PUT,DELETE,PATCH | 错误提示(消息) | 接口未实现 | 
另一种常见形式是使用 Envelope:
{
  "status": { },
  "data": { }
}
出错时可仅有 status 而无 data 字段。
本规范采用无 Envelope 的格式。
安全
RESTful API是无状态的也就是说用户请求的鉴权和 cookie 以及 session 无关,每一次请求都应该包含鉴权证明。
RESTful 服务使用 Oauth2 的方式进行调用授权,使用 http 请求头Authorization设置授权码; 必须使用User-Agent设置客户端信息, 无User-Agent请求头的请求应该被拒绝访问。
Request Header
User-Agent: Data-Server-Client
Authorzation: Bearer 383w9JKJLJFw4ewpie2wefmjdlJLDJF
说明:
- 授权码要放在 Http Header 中,可避免重定向传递时可能发生的授权码泄漏;
- 采用 JWT token。
缓存
聚合 API
把当前用户需要在第一时间内容加载的多个接口聚合成一个请求发送到服务端,服务端根据请求内容,一次性把所有数据合并返回。相比于页面级 API,具备更高的灵活性,同时又能很容易的实现页面级 API 的功能。
地址:/$version/aggApi
传入参数:
data:[
  {url:'api1',type:'get',data:{...}},
  {url:'api2',type:'get',data:{...}},
  {url:'api3',type:'get',data:{...}},
  {url:'api4',type:'get',data:{...}}
]
返回数据:
{
  status:0,
  msg:'',
  data:[
    {status:0,msg:'',data:[]},
    {status:-1,msg:'',data:{}},
    {status:1,msg:'',data:{}},
    {status:0,msg:'',data:[]},
  ]
}
API 文档
细节
- 使用ISO-8601格式表达时间字段,例如: 2014-04-05T14:30Z
- 响应:使用 HTTP Header 时,优先使用合适的标准头属性。用 X-作为前缀自定义一个头属性,例如:X-Result-Fields。
