開發(fā)規(guī)范

Web后端規(guī)范

不久將來愧沟,整個行業(yè)存在的唯一目的就是消費平臺上的數(shù)據(jù)蔬咬。你的API越容易使用鲤遥,那么就 會有越多的人去用它。立足現(xiàn)在林艘,展望未來盖奈,restful風格的api是我們必然的趨勢。

定義

  • 資源: 一個對象的實例
  • 集合:一群同種對象
  • HTTP:跨網(wǎng)絡的通信協(xié)議
  • 客戶端:可以創(chuàng)建HTTP請求的客戶端應用程序
  • 第三方開發(fā)者:這個開發(fā)者不屬于你的項目但是有想使用你的數(shù)據(jù)
  • 服務器:一個HTTP服務器或者應用程序狐援,客戶端可以跨網(wǎng)絡訪問它
  • 端點:這個API在服務器上的URL用于表達一個資源或者一個集合
  • 冪等:無邊際效應钢坦,多次操作得到相同的結(jié)果
  • URL段:在URL里面已斜杠分隔的內(nèi)容

URL

URI 表示資源,資源一般對應服務器端領(lǐng)域模型中的實體類啥酱。

URL規(guī)范

  1. 不用大寫字符
  2. 只用下劃線_連接
  3. 名詞表示資源的集合爹凹,使用復數(shù)

資源集合,單個資源

資源集合

/zooms/  # 所有動物園
/zooms/1/employees/  # id為1的動物園的所有職工

單個資源

/zooms/1/  # id為1的動物園

避免層級過深的url

/在url中表達層級镶殷,用于按實體關(guān)聯(lián)關(guān)系進行對象導航禾酱,一般根據(jù)id導航。

過深的導航容易導致url膨脹批钠,不易維護宇植,如 GET /zooms/1/areas/3/animals/4, 盡量使用查詢參數(shù)代替路徑中的實體導航埋心,如GET /animals/?zoom=1&area=3指郁。

Request

動詞

五個非常重要的HTTP動詞必須知道

  • GET (選擇):從服務器上獲取一個具體的資源或者一個資源列表,具備冪等性
  • POST (創(chuàng)建): 在服務器上創(chuàng)建一個新的資源拷呆, 不具備冪等性
  • PUT (更新):以整體的方式更新服務器上的一個資源闲坎, 具備冪等性
  • PATCH (部分更新):只更新服務器上一個資源的部分屬性, 具備冪等性
  • DELETE (刪除):刪除服務器上的一個資源茬斧, 具備冪等性

原則上腰懂,只允許客戶端或者第三方調(diào)用者使用這五個HTTP動詞進行數(shù)據(jù)交互,并且在URL段 里面不出現(xiàn)任何其他的動詞项秉。有寫操作的動詞性很強绣溜, 不太容易用一個名詞來表述,可以 邏輯上換一個方式來處理娄蔼,比如作廢一張訂單怖喻,可以采用兩種方式來實現(xiàn)。一是修改訂單的 狀態(tài)和相關(guān)字段(PATCH方法岁诉,這種的業(yè)務邏輯性不強锚沸,不清晰,不推薦)涕癣,另一種是把作廢 的訂單看作一種邏輯資源哗蜈,只需要在這種資源集合中使用POST方法創(chuàng)建一個資源即可。

另外一般情況下,GET請求要考慮緩存(客戶端距潘,服務器都要考慮)炼列,減少服務器檢索數(shù)據(jù)的 壓力。

版本化

API是服務器與客戶端之間的一個公共契約音比。對服務器上的API做了一個更改唯鸭,并且這些更改 無法向后兼容,那么就打破了這個契約硅确。這時候既要確保應用程序逐步的演變,又要讓客戶 端繼續(xù)可用明肮。那么必須在引入新版本API的同時保持舊版本API仍然可用菱农。所以接口必須版本 化

  1. 如果只是簡單的增加一個新的特性到API上,如資源上的一個新屬性或者增加一個新的端 點柿估,不需要增加API的版本循未。因為這些并不會造成向后兼容性的問題,只需要修改文檔即可秫舌。
  2. 申明不支持一個特性并不意味著關(guān)閉或者破壞它的妖。而是告訴客戶端舊版本的API將在某個 特定的時間被刪除,并且建議他們使用新版本的API足陨。
  3. 在URL中包含版本信息 GET /v1/zooms/ GET /v2/zooms/1/animals/

UserAgent

所有請求的Header信息中必須按照格式填寫User-Agent信息嫂粟,格式:

type|os|os_version|product|version|...

說明:

  • type: 客戶端類型, [MOBILE, DESKTOP, BROWSER]
  • os: 操作系統(tǒng), [Android, iOS, Chrome, IE ...]
  • os_version: 操作系統(tǒng)版本號, 包含完整信息,比如:Windows 7 Ultimate Service Pack 1 64bit
  • product: 產(chǎn)品, [KLICEN_APP, ZEUS(宙斯系統(tǒng)),ZEUS_APP(宙斯系統(tǒng)App), KLICEN_EP(凱勵程企業(yè)版) ,INSTALL(安裝工具), VUS(欣悅途), EWS(預警系統(tǒng))]
  • version: 客戶端版本號

手機端必須增加 手機品牌|手機型號|屏幕分辨率 沒有的用空表示墨缘;必須包含前面五個字段星虹。例如:

"User-Agent": "MOBILE|Android|7.0|KLICEN_APP|2.2.5|Dalvik/2.1.0 (Linux; U; Android 7.0; FRD-AL00 Build/HUAWEIFRD-AL00)|1080*1794|863549034263964"

Response

內(nèi)容類型

接口只提供兩種類型的返回內(nèi)容

  • 全部接口默認支持json
  • 部分接口支持excel表格/csv,數(shù)據(jù)導出作為一種返回格式镊讼,導出權(quán)限可配置 /animals/?zoom=1&format=excel # 導出id為1的動物園的所有動物數(shù)據(jù) ### 預期返回的內(nèi)容
  • GET /collection/?page=1&page_size=15: 返回一系列資源對象宽涌,分頁
  • GET /collection/resource/: 返回單獨的資源對象
  • POST /collection/: 返回新創(chuàng)建的資源對象
  • PUT /collection/resource/: 返回完整的資源對象
  • PATCH /collection/resource/: 返回完整的資源對象
  • DELETE /collection/resource/: 返回一個空文檔

使用ISO8601的國際化時間格式

接收和返回時間數(shù)據(jù)時只使用UTC格式

"create_at": "2012-01-01T12:00:00Z"

枚舉型

枚舉類型的字段返回其名值對:

{
    "key": 存儲值,
    "verbose": 顯示值
}

提供標準的時間戳

提供默認的資源創(chuàng)建時間,更新時間 created_at and updated_at, 例如:

{
  ...
  "created_at": "2012-01-01T12:00:00Z",
  "updated_at": "2012-01-01T13:00:00Z",
  ...
}

這些時間戳可能不適用于某些資源蝶棋,這種情況下可以忽略省去卸亮。

包裝

response 的 body 統(tǒng)一做如下包裝。示例:

{
    "code": 0,
    "msg": "請求成功"(用戶友好),
    "data": {
        "id": 1,
        "name": "張三"
    }
}

使用djangorestframework的情況下玩裙,可以在配置文件中配置REST_FRAMEWORK中的DEFAULT_RENDERER_CLASSESutils.renders.CustomJsonRender, 它的具體實現(xiàn)如下:

# -*- coding: utf-8 -*-
from rest_framework.renderers import JSONRenderer

class CustomJsonRender(JSONRenderer):
    """ 自定義返回數(shù)據(jù) Json格式
    {
        "code": 0,
        "msg": "success",
        "data": { ... }
    }
    """

    def render(self, data, accepted_media_type=None, renderer_context=None):
        if renderer_context:
            response = renderer_context['response']
            code = 0 if int(response.status_code / 100) == 2 else response.status_code
            msg = 'success'
            if isinstance(data, dict):
                msg = data.pop('msg', msg)
                code = data.pop('code', code)
                data = data.pop('data', data)
            if code != 0 and data:
                msg = data.pop('detail', 'failed')
            response.status_code = 200
            res = {
                'code': code,
                'msg': msg,
                'data': data,
            }
            return super().render(res, accepted_media_type, renderer_context)
        else:
            return super().render(data, accepted_media_type, renderer_context)

可能的錯誤信息的code可根據(jù)實際情況擴展, 所以要讓客戶端能獲取到這些code兼贸。

code碼

  • 0 OK - [GET]: 客戶端向服務器請求獲取數(shù)據(jù)成功
  • 201 CREATED - [POST/PUT/PATCH]: 客戶端向服務器請求改變數(shù)據(jù)成功
  • 204 NO CONTENT - [DELETE]: 客戶端要求服務器刪除一個資源,服務器刪除成功
  • 400 BAD REQUEST - [POST/PUT/PATCH]: 客戶端向服務器提供了不正確的數(shù)據(jù)献酗,服務器什么也不做
  • 401 UNAUTHORIZED - [*]: 用戶未認證
  • 403 FORBIDDEN - [*]: 已認證但權(quán)限不夠
  • 404 NOT FOUND - [*]: 客戶端引用了一個不存在的資源或集合
  • 500 INTERNAL SERVER ERROR - [*]: 服務器發(fā)生內(nèi)部錯誤寝受,客戶端無法得知結(jié)果,請求可能已經(jīng)處理成功

嵌套外鍵關(guān)系

序列化的外鍵關(guān)系建立在一個有嵌套關(guān)系的對象之上, 例如:

{
  "name": "成都動物園",
  "manager": {
    "id": 1
  },
  ...
}

而不是這樣, 例如:

{
  "name": "成都動物園",
  "owner_id": 1,
  ...
}

這種方式把相關(guān)聯(lián)的資源信息內(nèi)聯(lián)在一起罕偎,在返回更多信息時不用改變響應資源的結(jié)構(gòu), 例如:

{
  "name": "成都動物園",
  "owner": {
    "id": 1,
    "name": "張三",
    "email": "zhangsan@klicen.com"
  },
  ...
}

文檔

  • 避免使用文檔自動化生成器很澄,即便用了,你也要保證自己審閱過并讓它具有更好的版式。
  • 不要截斷示例中請求與響應的內(nèi)容甩苛,展示完整的東西蹂楣。并在文檔中使用高亮語法。
  • API的驗證授權(quán),包含獲取及使用驗證tokens
  • API穩(wěn)定性及版本控制, 包含如何選擇所需要的版本
  • 正確的響應和錯誤的響應都應該文檔化讯蒲,并說明在什么情況下會產(chǎn)生這些的錯誤

如果時間允許痊土,甚至可以創(chuàng)建一個控制臺來讓開發(fā)者可以立即體驗一下API的功能。

API分析

API分析就是持續(xù)跟蹤那些正為人使用的API的版本和端點信息墨林,這樣做的好處是:

  1. 決定什么時候不再支持某個版本
  2. 找到那些使用最廣泛的API赁酝,用其作為指導業(yè)務方向或者優(yōu)化效率的重要的依據(jù)
  3. 更多...

認證與安全

認證

采用OAuth2.0,OAuth2.0提供了一個非常好的方法去做這件事旭等。在每一個請求里酌呆, 你可以明確知道哪個客戶端創(chuàng)建了請求,哪個用戶提交了請求搔耕,并且提供了一種標準的訪問 過期機制或允許用戶從客戶端注銷隙袁,所有這些都不需要第三方的客戶端知道用戶的登陸認證 信息。

安全

這個暫時不是當前的重點弃榨,這里只列出幾個方向菩收,后期再完善

  • 采用https
  • 訪問頻次的控制
  • api訪問記錄的跟蹤分析
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鲸睛,隨后出現(xiàn)的幾起案子娜饵,更是在濱河造成了極大的恐慌,老刑警劉巖官辈,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件划咐,死亡現(xiàn)場離奇詭異,居然都是意外死亡钧萍,警方通過查閱死者的電腦和手機褐缠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來风瘦,“玉大人队魏,你說我怎么就攤上這事⊥蛏Γ” “怎么了胡桨?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞬雹。 經(jīng)常有香客問我昧谊,道長,這世上最難降的妖魔是什么酗捌? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任呢诬,我火速辦了婚禮涌哲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尚镰。我一直安慰自己阀圾,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布狗唉。 她就那樣靜靜地躺著初烘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪分俯。 梳的紋絲不亂的頭發(fā)上肾筐,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機與錄音缸剪,去河邊找鬼局齿。 笑死,一個胖子當著我的面吹牛橄登,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讥此,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼拢锹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了萄喳?” 一聲冷哼從身側(cè)響起卒稳,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎他巨,沒想到半個月后充坑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡染突,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年捻爷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片份企。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡也榄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出司志,到底是詐尸還是另有隱情甜紫,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布骂远,位于F島的核電站囚霸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏激才。R本人自食惡果不足惜拓型,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一额嘿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吨述,春花似錦岩睁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邓夕,卻和暖如春刘莹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背焚刚。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工点弯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人矿咕。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓抢肛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碳柱。 傳聞我的和親對象是個殘疾皇子捡絮,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)莲镣,斷路器福稳,智...
    卡卡羅2017閱讀 134,638評論 18 139
  • 一說到REST,我想大家的第一反應就是“啊瑞侮,就是那種前后臺通信方式的圆。”但是在要求詳細講述它所提出的各個約束半火,以及如...
    時待吾閱讀 3,417評論 0 19
  • 翻譯約定 primary data: 主數(shù)據(jù)resource identifier object 資源標識符對象r...
    sladeliu閱讀 2,384評論 0 2
  • API定義規(guī)范 本規(guī)范設計基于如下使用場景: 請求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請求頻率非常高越妈,建議使用雙通...
    有涯逐無涯閱讀 2,521評論 0 6
  • 話說海邊有兩戶漁夫,比鄰而居钮糖。簡稱稱為漁夫 A 和漁夫 B叮称。 漁夫 A 天天出海,每次都滿載而歸藐鹤。漁夫 B 一周只...
    煙雨國度閱讀 171評論 0 0