背景
在團隊兩年多陸續負責了幾個項目的開發上線已經代碼的review,特別是對老項目的重構過程中,發現之前的API設計是沒有任何規范和約定的,不同的開發同學有不同的習慣,因此需要一套規范去約定,現在分享一下我們目前試運行的一套規范,一起交流完善下。
WebAPI開發流程
- 第一步首先設計接口文檔,公司內部有一套自研的多人協作文檔系統,可以很好的做到這一步,並能很好的做好版本控制。如果公司內部沒有可以基於showdoc搭建一套
- 第二步有技術負責人確認接口以及字段的命名規范
- 第三步找對應API對接人,確認接口是否符合要求
這三步其實是個閉環,只有等到全部通過后才會正式開始開發API
命名規范
- 所有接口中不能出現拼音,統一用英語
- 不能有特殊字符,例如
/
- 接口命名遵循像個原則:
簡單
易懂
出入參規范
- 命名規范參考之前的一篇文章
- 若需要使用分割符,只可以使用中划線
-
- 禁止把所有數據庫字段全部返回,統一使用Dto,只返回調用方需要的字段
HTTP 請求方法使用規范
根據 HTTP 標准,HTTP 請求可以使用多種請求方法。
HTTP1.0 定義了三種請求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六種請求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
這里統一只是用 GET, POST,PUT,DELETE,PATCH
GET(SELECT): 從服務器獲取單個資源或者資源列表
POST(CREATE):發送請求創建一個新的資源
PUT(UPDATE):通過接口更新服務器上的資源信息,資源內容全量更新,提供資源全部字段信息
DELETE(DELETE):通過刪除服務器上的資源
PATCH(UPDATE) :通過接口更新服務器上的資源信息,資源內容增量更新,僅提供更新的屬性信息
具體使用規范,使用GET查詢獲取信息,POST創建新的資源,PUT修改已存在資源信息,DELETE刪除服務器資源信息,不強制要求使用Patch。
HTTP碼狀態使用規范
- 200 OK :成功
- 201 CREATED:成功創建數據 不強制使用,可以使用200
- 400 Bad Request:提交的參數錯誤。錯誤信息中要能體現哪個parameter沒有通過validation,為什么
- 401 Unauthorized:客戶端傳入了一個無效的auth token。客戶端需要更新token進行重試,包括讓用戶重新登陸
- 403 Forbidden:訪問被拒絕。最常見的case為水平越權。和401的區別是:如果改接口需要用戶登陸,無有效的登陸token,則返回401,表示登陸驗證未通過。登陸驗證通過后,但是因為要操作的資源沒有權限,則返回403.比如用戶更新或者刪除不屬於自己的resource
- 404 Not Found: 資源為找到
- 429 Too Many Requests:對於限頻接口請求次數超頻
- 500 Internal Server Error:應用服務器內部錯誤
- 502 Bad Gateway:網關或者代理處理請求錯誤
- 503 Service Unavailable:應用服務器暫時不可用
- 504 Gateway Timeout: 網關超時。網關從上游服務沒有在設定的時長內獲取到數據。
自定義Header規范,
x-[應用英文縮寫]-[語義化英文單詞說明用途]
示例:
X-Test-Authorization: qwaszxerdfcvtyghbn
返回規范
全部統一使用
Content-Type = application/json
格式返回
請求失敗的Response
- Http碼的狀態為200或者201
- code統一為 200,message 為
success
- isSuccess為
true
- 有返回值時,統一通過
data
返回,無返回值時為{}
,禁止使用null
返回 - 返回的header中追加標記本次請求的唯一值的
X-[項目英文縮寫]-ResponseId
{
"isSuccess": true,
"code": 200,
"message": "success",
"data": {
"id": 0,
"value": "Default"
},
"timestamp": "02/02/2020 13:19:22"
}
請求異常的Response
- Http碼的狀態根據上一小節介紹的按需使用
- code和http碼對應,message 為對應異常說明
- isSuccess為
false
data
統一返回為{}
- 返回的header中追加標記本次請求的唯一值的
X-[項目英文縮寫]-ResponseId
{
"isSuccess": false,
"code": 400,
"message": "Bad Request",
"value": {},
"timestamp": "02/02/2020 13:35:33"
}
接口注釋說明
約定
- 項目統一使用swagger
- 接口相關的文檔地址
- 相關jira.$ 分割
XXX-XXX $ XXX-XXX - 可能的返回的狀態碼
- 對應參數說明
/// <summary>
/// PUT api/values/5
/// </summary>
/// <param name="id">id</param>
/// <param name="dto">dto</param>
/// <remarks>
/// <url>doc: https://www.cnblogs.com/sagecheng/</url> <br/>
/// <br/>
/// <br/>
/// <jira>jira: XXX-XXX</jira>
/// </remarks>
/// <returns></returns>
/// <response code="200"> success </response>
/// <response code="400">If the id is null</response>
/// <response code="404">If the id is not found</response>
[HttpPut("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ApiResult Put(int id, [FromBody] ValueDto dto)
{
var info = values.FirstOrDefault(o => o.Id == id);
if (info == null)
{
throw new ApiException(StatusCodes.Status404NotFound, "Not Found");
}
info.Value = dto.Value;
return ApiResult.GetSuccessResult();
}
Swagger相關效果
整體效果
注釋效果