微服務(wù) REST API 設(shè)計(jì)原則

REST API 設(shè)計(jì)原則

REST API 的設(shè)計(jì)很有講究,我司總結(jié)了一些規(guī)范和原則,詳見 Cisco REST API 規(guī)范,編譯如下:

REST 方法

    1. GET 方法的響應(yīng)是由所請求URL代表的資源的表示
    1. GET 方法不會(huì)改變請求URL所代表的資源
    1. POST 請求在所請求的URL 路徑下創(chuàng)建一個(gè)新的資源以作為葉子節(jié)點(diǎn)
    1. POST 響應(yīng)體或者為空(響應(yīng)狀態(tài)碼為204), 或者是所創(chuàng)建的資源的表示(響應(yīng)狀態(tài)碼為201)
    1. PUT 請求一個(gè)URL, 如果沒有相應(yīng)的資源存在, 就會(huì)創(chuàng)建一個(gè)相應(yīng)的新資源
    1. PUT 請求一個(gè)URL, 如果已經(jīng)有相應(yīng)的資源存在, 就會(huì)以請求體中的內(nèi)容覆蓋這個(gè)資源
    1. PUT 響應(yīng)體是所請求的URL代表的資源的表示, 包含了這個(gè)請求所作出的修改
    1. DELETE 請求一個(gè)URL, 會(huì)刪除相應(yīng)的已存在的資源
    1. DELETE 的響應(yīng)體或者為空(響應(yīng)碼為204) , 或者是資源的表示(響應(yīng)碼為200)
    1. PATCH 請求一個(gè)URL, 是部分地修改相應(yīng)的資源的狀態(tài), 參見 RFC6902
    1. PATCH 響應(yīng)返回所請求的URL代表的資源的表示, 包含了這個(gè)請求所作出的修改

URL 路徑

    1. URL 路徑表示一個(gè)資源, 或一組資源的集合
    1. URL 路徑的開頭形式一般為 /{service}/{apiclass}/v{version}
    1. 集合 URL 的最后一段是一個(gè)名詞算數(shù), 描述所包含資源的類型
    1. 資源 URL 路徑的最后一段的父節(jié)點(diǎn)是復(fù)數(shù)名詞,表示資源集合。
    1. 資源 URL 路徑的最后一段是其容器內(nèi)資源的唯一標(biāo)識(shí)符。
    1. URL 路徑各段是字母或者數(shù)字,遵循駝峰命名法的約定(第一個(gè)字符是小寫)
    1. URL 路徑各段的命名要直觀,明確,簡潔, 既不拖沓, 又一目了然

URL 查詢參數(shù)

    1. 表示日期/時(shí)間的URL查詢參數(shù)采用 RFC-3339 的 iso-date-time 格式
    1. 表示持續(xù)時(shí)間的URL查詢參數(shù)采用 RFC-3339 的 duration 格式
    1. 表示時(shí)間間隔的URL查詢參數(shù)采用 RFC-3339 的 period 格式
    1. URL查詢參數(shù)在語義上以及在API中其他位置同名的參數(shù)要保持統(tǒng)一
    1. 如果選擇所查詢資源的特定字段, URL查詢參數(shù)要符合字段命名和標(biāo)準(zhǔn)規(guī)范. 比如: ?fields=subject,body,createTime
    1. 與分頁檢索有關(guān)的URL查詢參數(shù)符合分頁查詢形式: ?page=1&size=20&sort=username,asc
    1. URL查詢參數(shù)名稱是字母數(shù)字,并遵循駝峰命名法的約定(第一個(gè)字符是小寫)
    1. URL查詢參數(shù)名稱應(yīng)該直觀,明確,簡潔。

Resource Representations 資源表示

    1. 資源的表示通常編碼為 application/json, 除非資源為其他標(biāo)準(zhǔn)的多媒體類型, 比如 png, vcard 等等
    1. 資源的集合通常編碼為 application/json, 集合以 json 數(shù)組形式給出
    1. 如果一個(gè)集合支持分頁, 那么這個(gè)集合的表示應(yīng)該包括一些標(biāo)準(zhǔn)的分頁屬性, 比如集合放在 results 數(shù)組中, 加上 start(開始), size(頁長), total(總數(shù))等屬性, 還可以包含一個(gè) _links 對象, 包括 first, prev, next, last, self 這些鏈接作為屬性
    1. 一個(gè)資源推薦在資源查詢的響應(yīng)中提供一個(gè) url 屬性, 表示這個(gè)資源自己的鏈接
    1. 一個(gè)資源不推薦包含另一個(gè)服務(wù)所擁有和負(fù)責(zé)的資源, 可以給出一個(gè)資源的鏈接, 使用絕對路徑和規(guī)范的 URL 形式
    1. 在資源的響應(yīng)體中一般不包括狀態(tài)信息, 以免和本身http status code 發(fā)生語義上的不一致
    1. 在返回一個(gè) 4xx 或 5xx 的 HTTP 響應(yīng)碼時(shí), 響應(yīng)主體中就包括標(biāo)準(zhǔn)的錯(cuò)誤信息, 比如: errorCode, errorReason, errorMessage等

JSON Attributes

    1. 屬性名稱直觀,明確,簡潔。
    1. 屬性名稱是字母數(shù)字,遵循camelCase約定(第一個(gè)字符是小寫)。
    1. 表示日期/時(shí)間的屬性采用RFC-3339 iso-date-time格式,并具有UTC偏移量。
    1. 表示持續(xù)時(shí)間的屬性采用RFC-3339持續(xù)時(shí)間格式。
    1. 表示時(shí)間間隔的屬性采用RFC-3339周期格式。
    1. 表示二進(jìn)制值的屬性使用JSON本機(jī)布爾類型進(jìn)行編碼。
    1. 表示數(shù)組的屬性被命名為復(fù)數(shù)名詞。
    1. 表示非數(shù)組的屬性被命名為單數(shù)名詞。
    1. 表示其他資源鏈接的屬性以絕對和規(guī)范URL 的形式提供。
    1. 屬性名稱在各個(gè)地方應(yīng)該在保持統(tǒng)一的語義
    1. 表示枚舉類型的屬性要具有明確定義的合法值和語義。
    1. 缺少JSON屬性與顯式賦值為null之間沒有語義上的區(qū)別。

Security

    1. REST 請求必需使用 OAuth2 之類的協(xié)議進(jìn)行身份驗(yàn)證,授權(quán)
    1. REST 請求具有關(guān)于訪問所需資源的要有明確的授權(quán)策略。
    1. 必須驗(yàn)證包含個(gè)人身份信息(PII)的REST請求。
    1. REST請求不允許用戶之間無意的內(nèi)容或PII泄漏。
    1. 必須通過安全通道(HTTPS)進(jìn)行身份驗(yàn)證的 REST 請求。
    1. REST請求不可以在URL中包含身份驗(yàn)證,授權(quán)或 PII 信息。

API Documentation

    1. API 文檔應(yīng)該由源代碼或注釋自動(dòng)生成, 比如 swagger 之類的
    1. 自動(dòng)生成的文檔應(yīng)該對于資源和所提供方法提供足夠的描述信息
    1. 自動(dòng)生成的文檔應(yīng)該對于認(rèn)證,授權(quán)策略及調(diào)用方法提供足夠的描述信息
    1. 自動(dòng)生成的文檔應(yīng)該對于URL 路徑, 調(diào)用參數(shù)等提供足夠的描述信息
    1. 自動(dòng)生成的文檔應(yīng)該對于表示資源的 JSON 屬性提供足夠的描述信息
    1. 自動(dòng)生成的文檔應(yīng)該對于預(yù)計(jì)的錯(cuò)誤觸發(fā)條件和響應(yīng)碼提供足夠的描述信息

API 文檔工具

API 文檔的生成有很多框架和工具, 現(xiàn)在比較流行的有三種:

1) RESTful API Modeling Language (RAML)

顧名思義, 它是一個(gè)RESTful API 的建模語言, 好象UML 類圖那樣, 通過這個(gè)建模語言描述的 raml 文件來定義你的 API 格式, 然后通過工具(raml2html)來生成易讀的HTML 文檔, 你需要手動(dòng)編寫 raml 文件, 然后生成所需文檔.
它已經(jīng)形成了一套規(guī)范和工具, 例如
? API Workbench: 一個(gè)功能完善的IDE, 可用來設(shè)計(jì), 構(gòu)建,測試 RESTful API, 和相應(yīng)文檔生成和分享
? RAML Java Client Generator: 一個(gè)可以基于 RAML 文檔自動(dòng)生成Java 客戶端代碼的工具
? RAML2HTML: 一個(gè)Node.js 工具, 將 RAML 文件轉(zhuǎn)化成易于閱讀的 HTML文檔.

例如以如下 raml 來定義API

#%RAML 1.0
title: Hello world # required title
version: 1
baseUri: http://example.com/{version}
documentation:
  - title: Welcome
    content: |
      Welcome to the Example Documentation. The Example API allows you
      to do stuff. See also [example.com](https://www.example.com).
  - title: Chapter two
    content: |
      More content here. Including **bold** text!
/helloworld: # optional resource
  description: This is the top level description for /helloworld.

  get: # HTTP method declaration
    responses: # declare a response
      200: # HTTP status code
        body: # declare content of response
          application/json: # media type
            type: | # structural definition of a response (schema or type)
              {
                "title": "Hello world Response",
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string"
                  }
                }
              }
            example: # example how a response looks like
              {
                "message": "Hello world"
              }
  /test:
    displayName: TEST
    get:
      description: a sub resource

  /{id}:
    uriParameters:
      id:
        type: string
        description: account identifier
        minLength: 1
        maxLength: 10

    get:
      headers:
        Authorization:
          type: string
          description: Basic authentication header
          example: |
            Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    put:
      body:
        application/x-www-form-urlencoded:
          properties:
            name:
              description: name on account
              type: string
              examples:
                example1: Naruto Uzumaki
                example2: Kevin Renskers
            gender:
              enum: ["male", "female"]

然后安裝 raml2html

npm i -g raml2html
npm i -g raml2html-markdown-theme

  • 執(zhí)行
raml2html api.raml > api.html

生成的 API html 文件如下

詳情參見 https://github.com/raml2html/raml2html

2) Swagger UI

它是一個(gè)更加流行的文檔生成框架, 強(qiáng)調(diào)從代碼中全自動(dòng)生成 API 文檔
這個(gè)框架有三個(gè)主要的組件:
? Swagger 是它的規(guī)范部分, 一套描述 RESTful 服務(wù)的規(guī)則, 類似于 RAML
? Swagger UI 是它的渲染部分, 它就象 RAML2HTML 那樣生成易讀的HTML文檔, 用戶無需用任何客戶端就可基于Swagger 規(guī)范用它自動(dòng)生成的客戶端進(jìn)行API測試
? Springfox 是它的生成部分, 通過Java代碼, SpringMVC 和 Swagger 的注解來自動(dòng)生成API 文檔.

3) Spring REST Docs

這是 Spring 生態(tài)圈, 它基于API 測試來生成 AsciiDoc 文檔, 你也可以自己編寫一些描述性的 AsciiDoc 文檔, 這些 AsciiDoc 文檔可以通過它提供的 maven 插件自動(dòng)生成易讀的 HTML 文檔, 相比前兩者, 它介于手動(dòng)和全自動(dòng)之間, 相當(dāng)于半自動(dòng)的工具.
如果你是一個(gè)新項(xiàng)目, 在設(shè)計(jì)階段就可以采用 RAML 來定義你的 API, 如果是老項(xiàng)目, 采用 Swagger 會(huì)更省力, 當(dāng)然 Spring REST Docs 更加符合測試驅(qū)動(dòng)開發(fā)的理念, 既可以通過測試來自動(dòng)生成文檔, 也可以手動(dòng)添加說明, 推薦使用

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一說到REST,我想大家的第一反應(yīng)就是“啊,就是那種前后臺(tái)通信方式?!钡窃谝笤敿?xì)講述它所提出的各個(gè)約束,以及如...
    時(shí)待吾閱讀 3,594評論 0 19
  • 去年有段時(shí)間得空,就把谷歌GAE的API權(quán)威指南看了一遍,收獲頗豐,特別是在自己幾乎獨(dú)立開發(fā)了公司的云數(shù)據(jù)中心之后...
    騎單車的勛爵閱讀 21,080評論 0 41
  • 感恩我有一個(gè)安靜的學(xué)習(xí)環(huán)境,一切都是那么祥和美好,感恩小巧的紫砂壺,還有壺里那輕柔的玫瑰花水。感恩窗外藍(lán)藍(lán)的天,綠...
    Daisy明閱讀 328評論 0 0
  • 你或許是最能直面狗生的小黑了!無論如何都坐的筆直
    李安聞閱讀 153評論 0 0
  • 因?yàn)楦淖兪峭纯嗟模院芏嗳丝傁胫寗e人改變,而自己不想改變。 不想改變的人是自私的,改變確實(shí)是痛苦的,但是經(jīng)歷這...
    恬淡羅羅閱讀 178評論 0 1

友情鏈接更多精彩內(nèi)容