團隊中若是不一樣的項目,不一樣的人員可能在接口設計上有許多不統一的地方。致使了開發效率低下的問題。
因爲我在工做中遇到了,因此整理下來,說一說本身的一些見解。javascript
由於每一個人對本身使用語言有不一樣的理解、HTTP協議熟悉程度不一樣、思惟邏輯、開發經驗不同。對接口規範有想法的人應該提出本身的觀點,給出本身的理由。讓別人去評價,討論出一套統一的規則,最終統一成一個內部的標準。
造成統一標準後由相關人員寫出示例。例如前端要對GET請求針對jQuery.ajax
、fetch
、axios
等請求庫給出示例代碼。之後直接參照示例代碼進行開發。html
因爲每一個項目在定義接口時有許多不一樣的方式,我根據以往的經驗,從請求方法、請求頭、請求體、響應狀態碼、響應體等幾個方面對接口的規範說說本身的見解。前端
咱們不一樣的項目使用的請求方式大概有兩種:java
若是使用前者,PSOT的URL中應該指明要執行的動做,然後者不須要指定。ios
POST /api/user/add HTTP/1.1 POST /api/user/set HTTP/1.1 POST /api/user/delete HTTP/1.1 # 這裏例子中約定PUT是新增,POST是修改 POST /api/user HTTP/1.1 PUT /api/user HTTP/1.1 DELETE /api/user HTTP/1.1
至於使用前者仍是後者,我更傾向於前者。
若是使用後者時,什麼狀況下使用PSOT、什麼狀況下使用PUT,搜索到了到了一些資料,但看不懂。git
接口URL應該見名知意,有必定的規律。
這裏我不太懂,就不作過多贅述。github
前端請求中不該該有undefined
,由於後端不支持(json也不支持)該數據類型。
若是Content-Type
爲multipart/form-data
,前端不該該傳null,由於會被轉化成字符串,後端不能判斷出這是用戶輸入仍是null類型。ajax
每一個項目應該約定請求時下面這些數據表明什麼意思json
GET請求應該讀取數據,不該該產生任何的「反作用」操做。
這裏要注意一點瀏覽器對URL長度是有限制的,若是查詢的URL長度過長會引發不可預期的後果。能夠採用POST/PUT進行查詢。axios
GET請求的參數應該放在請求的URL中而不該該放在請求體中。
例以下面是一個標準的這個GET請求(不相關HTTP頭字段已剔除)
GET /api/user?userId=12345 HTTP/1.1 Host: http://www.example.com
這三種請求方法傳參數格式都相同,下面以POST爲例。
POST類型使用的方式很是多樣,見識過各類各樣奇葩的方式,也是耽誤時間最長的,嚴重影響開發進度。這裏只討論我認爲標準的方式。
POST請求用於新增、修改或刪除數據,少數狀況下用於查詢數據。
POST請求的參數必須放在請求體中。
而POST的請求方式有四種方式:
這幾種方式經過HTTP頭中的Content-Type
頭字段進行控制。
multipart/form-data
咱們如今使用的最多的是multipart/form-data
。
POST /api/user/set HTTP/1.1 Host: http://www.example.com Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userName" 張三 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userId" 123456 ------WebKitFormBoundary2KbanAZwv0mKceX0--
這種方式不適合複雜數據類型的傳遞,例若有個接口須要同時修改多個用戶:
const userList = [ { userID: 123, userName: '張三', isAdmin: true, }, { userID: 456, userName: '李四', isAdmin: false, }, ];
那麼在POST請求時只能這麼作
POST /api/userlist/set HTTP/1.1 Host: http://www.example.com Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2KbanAZwv0mKceX0 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userID" 123,456 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="userName" 張三,李四 ------WebKitFormBoundary2KbanAZwv0mKceX0 Content-Disposition: form-data; name="isAdmin" 1,0 ------WebKitFormBoundary2KbanAZwv0mKceX0--
更重要的是這種方式不支持數據類型,傳入的全部格式的數據都會轉成字符串類型。後端常常要使用1表示true,須要將數組或對象拆分開。
application/json
這是我推薦使用的方式,有效的彌補了multipart/form-data
的缺陷。
但不知什麼緣由如今咱們團隊基本不使用這種方式。application/json
也有一個缺陷就是不支持上傳文件(有特殊的方法這裏也不建議使用),想上傳文件仍是使用multipart/form-data
。
下面是請求示例
POST /user HTTP/1.1 Host: http://www.example.com Content-Type: application/json;charset=utf-8 [{"userID":123,"userName":"張三","isAdmin":true},{"userID":456,"userName":"李四","isAdmin":false}]
不知道服務器對於不一樣的處理會返回什麼樣的狀態碼,這裏不作討論。
咱們會返回一個邏輯狀態碼code
與提示信息msg
,響應體像下面這樣。
{"code":200,"msg":"處理成功!","data":{}}
在此基礎上增長一些限制:
易於擴展,例如當前接口是用戶列表頁,data使用數組。v2版本接口加入了分頁查詢,就必須使data變爲對象類型了。
複雜類型包括數組與對象。
爲了方便閱讀,這裏將json字符串轉化爲了JS對象。
const resBody = { code: 200, msg: '處理成功', data: { list: [ { userID: 123, userName: '張三', }, ], }, };
若是沒有數據的時候返回
const resBody = { code: 200, msg: '處理成功', data: { list: null, }, };
這樣前端在遍歷list時,null會致使代碼出錯,應該始終保證該字段的數據類型不變,正確返回方式以下。
const resBody = { code: 200, msg: '處理成功', data: { list: [], }, };
若是你有其餘補充或糾正,歡迎👏評論。
同時發表在GitHub。