Skip to content

HTTP API 接口设计约定(非 REST 风格)

基本原则

API 应是 可预期 的以及 可阅读 的,接受 form-encoded 请求正文,返回 JSON-encoded 响应, 使用标准的 HTTP 响应代码 ,认证(OAuth 2.0)和参数。 所有请求和响应的编码均为 UTF-8。

基础返回字段

除了返回成功 HTTP Status Code 外,还在 Response Body 中携带如下 JSON 信息。

字段类型描述
statusinteger必须。自定义返回状态码,可以和 HTTP Status Code 相同,如 200, 300, 也可自定义 20001
messagestring必须。返回信息。例如:成功描述,失败原因,错误异常等,
dataObject | Array<any>必须。返回结果集。注意:不建议返回null或者undefine,应使用code错误码提示无返回数据。

分页和排序

分页请求示例参考: https://www.baeldung.com/spring-data-web-support#the-pageablehandlermethodargumentresolver-class

URL 形式为:

js
http://ip:port/api/products?page=2&size=10&sort=name&sort=unitPrice,desc

分页 query string 参数约定

字段类型描述
pageinteger必须。获取的页码,不传参时默认为 0,而 0 是获取第一页
sizeinteger必须。获取记录数,不传参时默认为 10,最大 50
sortstring可选。可以有多个,每个都是逗号分隔的排序字段和排序关键字,排序关键字取值 'asc' 或 'desc',关键字未指定时默认 'asc'

分页返回字段约定

字段类型描述
totalElementsinteger必须。总记录数
sizeinteger必须。每页记录数
numberinteger必须。当前页,默认从 1 开始
contentArray<any>必须。返回集合

注意,返回的分页数据内容应该被包裹在基础返回字段 data 中。

错误返回

除了返回错误 HTTP Status Code 外,还在 Response Body 中携带如下 JSON 信息。

字段类型描述
timestampstring必须。时间戳
statusinteger必须。自定义返回状态码,可以和 HTTP Status Code 相同,如 404, 500, 也可自定义 40001
errorstring必须。简要错误描述
exceptionstring必须。异常信息
messagestring必须。详细错误描述
pathstring必须。请求 url

异常发生时返回结果的 Response Body 示例如下:

json
{
    "timestamp": "2021-12-29 09:30:16",
    "status": 404,
    "error": "Not Found",
    "exception": "org.springframework.web.server.ResponseStatusException",
    "message": "Product not found, id: 1000",
    "path": "/products/1000"
}

URL 命名规范

  • 约定只使用 GET 和 POST 两个 HTTP 动词发起请求
  • 约定 URL 全小写,尽量避免用特殊字符。(传参的 query string 的值或锚点内容不在此约束内)
  • 约定 URL 采用短横线 - 分隔多个单词,包括 path 和 query string 中的键名
  • 约定不使用英文复数表达,比如使用 person 不使用 people,使用 task 不使用 tasks

URL Path 风格:/api/<子系统>/<版本号>/<模块>/<业务对象>/<动词或动词短语>

其中:

  • 子系统:子系统标识,例如 cms(内容平台业务)、project(项目管理业务)
  • 版本号:接口版本号,例如 v1,v2
  • 模块:子系统的模块,如果没有可以省略,例如 wbs(项目管理系统中的工作分解模块)
  • 业务对象:例如 person、task
  • 动词或动词短语:需要执行的动作

常用的动词有(建议而非约束)

词汇HTTP verb描述
createPOST创建
updatePOST更新或修改
deletePOST删除单个或批量删除,传参为 json 包裹的 ids 数组,一般实现为逻辑删除
infoGET获取符合条件的单个对象信息
get-*GET获取符合业务诉求的单个对象信息,一般不会单写 get 动词
get-*-listGET获取符合业务诉求的列表信息
findGET查询符合条件的对象列表,可以为空列表,不能为空值
searchPOSTfind 类似,但是为 POST 查询
queryPOST多用于带统计性质的查询
importPOST导入,一般是从外部文件批量导入,返回结果和/或过程日志
exportPOST导出,一般是将数据导出到外部文件,返回文件链接

以下是一些示例

js
// 获取单个租户信息
GET /api/cms/v1/tenant/info?id=10001
GET /api/cms/v1/tenant/info?name=百度在线网络技术(北京)有限公司

// 获取题目的正确答案,返回单个对象
GET /api/cms/v1/question/get-answer?question-id=60001

// 获取考试的正确答案,返回列表
GET /api/cms/v1/exam/get-answer?exam-id=80001
// 或者先找到考试对应的试卷,再找试卷的答案
GET /api/cms/v1/test-paper/get-answer?test-paper-id=70001

// 获取考生参加过的、正在进行中的考试列表
GET /api/cms/v1/exam/get-participated-list?examinee-id=20001&exam-status=1

// 获取考生的考试答案,返回列表
GET /api/cms/v1/exam/get-examinee-answer?exam-id=80001&examinee-id=20001

// 常规列表查询,默认就是分页查,不可以一次性返回全部数据
GET /api/cms/v1/tenant/find
GET /api/cms/v1/tenant/find?page=0&size=10&sort=name,asc&sort=update_time,desc

// 根据分类和题干关键字查询试题
POST /api/cms/v1/question/search
{
  stem_containing: "压缩机", 
  type: 1, // 单选题
  tags: [
    "班长"
  ],
  pageable: {
    page: 0,
    size: 10
  }
}

// 获取答错率最高的前 5 道试题
// 较耗资源的操作采用 POST 一定程度避免拷贝链接后误调用引起的资源消耗
POST /api/cms/v1/question/query-top-wrong-rate
{
  limit: 5
}

// 导出试卷,高耗操作还是采用 POST
POST /api/cms/v1/test-paper/export
{
  id: 70001,
  output_type: "docx"
}

工具约定

约定在 Apifox 做接口设计。设计完成后可以选择把 API 设计结果导出为 OpenAPI 3.0 YAML 格式,然后导入腾讯云 CODING 项目中的 API 文档,以便使用。

建议:

  • 先在 Apifox 完成设计,再开始编码实现;
  • 不使用 Apifox 的自动生成客户端代码;
  • API 接口分类面向业务模块而非库表;

参考: https://coding.net/help/docs/document/api/import/openapi.htmlhttps://mermade.github.io/openapi-gui/