使用 Swagger 文档化和定义 RESTful API
大部分 Web 應(yīng)用程序都支持 RESTful API,但不同于 SOAP API——REST API 依賴于 HTTP 方法,缺少與 Web 服務(wù)描述語言(Web Services Description Language,WSDL)類似的語言來定義使用者與提供者之間的請求和響應(yīng)結(jié)構(gòu)。由于沒有充分的合同服務(wù),許多 REST API 提供者使用 Microsoft Word 文檔或維基頁面來記錄 API 用法。這些格式使協(xié)作和文檔版本控制變得很困難,尤其對于有許多 API 或資源的應(yīng)用程序,或者在 API 采用迭代式開發(fā)方式時。這些文檔類型在集成到自動化測試應(yīng)用程序中時變得更難。
開源?Swagger?框架幫助 API 使用者和開發(fā)人員糾正了這些問題。該框架為創(chuàng)建 JSON 或?YAML(JSON 的一個人性化的超集)格式的 RESTful API 文檔提供了?OpenAPI 規(guī)范(以前稱為 Swagger 規(guī)范)。Swagger 文檔可由各種編程語言處理,可在軟件開發(fā)周期中簽入源代碼控制系統(tǒng)中,以便進(jìn)行版本管理。
但是 Swagger 本身也有不足之處。當(dāng)我們使用該框架記錄自己的 API 時,會發(fā)現(xiàn)我們的文檔需求與 Swagger 的基本功能之間存在空白。我們將介紹我們在文檔化過程中遇到的挑戰(zhàn),并展示如何通過以下方法解決它們:
- 實(shí)現(xiàn) Swagger 擴(kuò)展
- 簡化 Swagger 的功能來聚合文檔
- 創(chuàng)建一個輸出 Swagger 文檔為 HTML 頁面的工具
我們開發(fā)的解決方案可通過下載獲得(參見“下載”)。您可以修改我們的示例,以便使用 Swagger 為您自己的 RESTful API 創(chuàng)建文檔,并(使用您在本文中學(xué)到的技術(shù))創(chuàng)建您自己的 Swagger 定制化。
使用 Swagger
一些 Swagger 編輯工具可幫助您輕松地創(chuàng)建 API 文檔,確保它們遵守 OpenAPI 規(guī)范。舉例而言,通過使用?Swagger Editor,您可以創(chuàng)建或?qū)?API 文檔,并在一個交互式環(huán)境中瀏覽它。右側(cè)的顯示窗格顯示了格式化的文檔,反映了您在左側(cè)窗格中的代碼編輯器中執(zhí)行的更改。代碼編輯器指出了所有格式錯誤。您可以展開和折疊每個窗格。
以下是您導(dǎo)入 leads.yaml 定義后的 Swagger Editor UI 外觀:
放在屏幕截圖上的紅色箭頭表示基于 OpenAPI 規(guī)范的 leads.yaml 文件中的?post:?和?get:?定義,與預(yù)覽文檔中?POST?和?GET?API 的文檔之間的對應(yīng)關(guān)系。
如果使用 Eclipse 作為 IDE,您可以使用?YEdit,它會檢查并突出顯示 YAML 語法,還會提供編輯和格式化功能。
擴(kuò)展 Swagger
現(xiàn)有的工具使編輯 Swagger API 文檔變得很容易,但某些文檔場景帶來了一些挑戰(zhàn)。以下這些是我們在使用 Swagger 記錄自己的 API 文檔時遇到的一些實(shí)際問題:
- API 使用者需要獲得特定于我們的 API 的信息,但 OpenAPI 規(guī)范不包含該信息的標(biāo)準(zhǔn)。
- API 使用者需要請求和響應(yīng)示例,但現(xiàn)有的編輯器無法包含它們。
- 我們需要提供一個容易閱讀的富文檔,其中包含可供 API 使用者使用的示例,最好是采用在線 HTML 文檔形式。
為了解決這些問題,我們根據(jù) OpenAPI 規(guī)范創(chuàng)建了自己的屬性、工具和模板。
擴(kuò)展屬性
您可以使用?x-?擴(kuò)展屬性來擴(kuò)展 Swagger。以下是我們?yōu)樽约旱?API 專門定制的一些擴(kuò)展,以及它們的用法示例:
以下屬性用于 API 有效負(fù)載或響應(yīng)字段:
- x-sc-crud:記錄一個 API 字段的有效創(chuàng)建、讀取、更新和刪除(CRUD)操作:
1 x-sc-crud:? [ read, update, create ] - x-sc-required:指示此字段需要哪些 CRUD 操作:
1 x-sc-required: [ create ] - x-sc-fieldmap:記錄與指定的 API 字段關(guān)聯(lián)的數(shù)據(jù)庫表和 UI 字段:
1 2 3 x-sc-fieldmap: ??table: TASKS_RELATED_TO ??uifieldname: Related to - x-sc-enum:記錄 API 字段的有效值。可以不使用靜態(tài)值列表,而指定一個返回當(dāng)前的可能值集合的 API。
1 2 x-sc-enum: ??api: /leads/enum/alt_address_country - x-sc-comments:為?description?屬性提供補(bǔ)充,用于捕獲給定 API 字段的額外的臨時信息:
1 2 x-sc-comments: ??- readonly in UI, aka Domestic Buying Group or DB
下面的清單是?Lead?模塊中的?lead_source?API 字段的 YAML 定義中的?x-sc?屬性的示例:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | lead_source: ??type: string ??maxLength: 100 ??externalDocs: ????description: Lead Source // Current (0100) // Approved // op - Opportunity ????url: https://w3.ibm.com/standards/information/tmt/output/Approved/ ????ibmww/op/bds/Opportunity_Management/Lead_Source.html # # lead_source value is returned when retrieving a lead, # and you can set its value when creating or updating a Lead. # ??x-sc-crud:? [ read, update, create ] ??? # # The lead_source is a required field when creating a Lead. # ??x-sc-required: [ create ] ??? # # You can retrieve valid lead_source values from the # /leads/enum/lead_source API. # ??x-sc-enum: ????api: /leads/enum/lead_source ????AVL: ??????dictionary_name: leads_lead_source_dom ????? ??example: LinkedIn ????? # # The value of lead_source is saved in the LEADS table. # In UI, you can find lead_source under the "Lead Source" label. # ??x-sc-fieldmap: ????table: LEADS ????uifieldname: Lead Source |
以下屬性擴(kuò)展了 API 操作的描述:
- x-sc-samples:記錄示例。此屬性包含對文檔的示例小節(jié)的 JSON 引用列表:(參見“包含示例”小節(jié)了解更多信息)
1 2 3 x-sc-samples: ??- $ref: '#/x-sc-samples/leads-post-create-lead' ??- $ref: '#/x-sc-samples/leads-post-create-lead-employeecnum' - x-sc-APIm-plans:列出包含該操作的?IBM API Connect(以前稱為 IBM API Management)計劃。我們希望捕獲特定于 API Manager 的信息:
1 2 x-sc-APIm-plans: ??- salesconnect_leads_read
以下是?/leads?API 端點(diǎn)的 HTTP?POST?方法的 YAML 資源中的?x-sc?屬性示例:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | paths: ?????? ??/leads: ????parameters: ??????- $ref: 'MASTER#/parameters/OAuthToken' ??????- $ref: 'MASTER#/parameters/ContentType' ??????? ????post: ??????summary: create lead ??????tags: [ leads ] # # Use the x-sc-APIm-plans property to specify that this endpoint # is in APIm's salesconnect_leads_create plan. # ??????x-sc-APIm-plans: ????????- salesconnect_leads_create ????????? ??????description: | ????????<p>API to create a lead.</p> # # Use the x-sc-samples property to refer to samples of the usage # of the /leads API. # ??????x-sc-samples: ????????- $ref: '#/x-sc-samples/leads-post-create-lead' ????????- $ref: '#/x-sc-samples/leads-post-create-lead-employeecnum' ???????????? ????????? ??????parameters: ????????- name: lead_definition ??????????in: body ??????????description: definition of lead to be created ??????????schema: ????????????$ref: '#/definitions/LeadObject' ????????????? ??????responses: ????????200: ??????????$ref: '#/responses/LeadObjectResponse' ??????????? ????????422: ??????????description: | ?????????<p>scenarios</p> ?????????<ul> ?????????<li>missing required field</li> ?????????<li>invalid values for optional fields</li> ?????????<li>et cetera</li> ?????????</ul> |
包含示例
盡管 Swagger 是一個定義 RESTful API 的強(qiáng)大工具,但它未提供用于包含 HTTP 請求和響應(yīng)示例,或者用于為開發(fā)人員添加已編寫文檔的途徑。
為了包含請求和響應(yīng)示例,我們擴(kuò)展了該規(guī)范,并再次使用了 YAML 來記錄示例。我們將自己的示例放在一個分離的模式(schema)中,這樣就不會讓主要 API 文檔過于復(fù)雜。
下面的?leads-post-create-lead?示例告訴使用者如何調(diào)用?/leads?API 的 HTTP?POST?方法,描述 URL、方法、頭文件、URL 參數(shù)、輸入(示例有效負(fù)載)和響應(yīng):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | x-sc-samples: ??leads-post-create-lead: ????title: Create a New lead ????description: | ??????This sample creates a new lead, and assigns it to a user specified via sugar user id. ?????????? ????method: POST ????url: https://w3-dev.api.ibm.com/sales/development/salesconnect/leads ??????? ??????? ????headers: | ??????Content-Type: application/json ??????Oauth-Token:? 111e567a-7624-35f7-ed82-540f5a954312 ??????? ??????? ????Parameters:? ?client_id={client_id}&client_secret={client_secret} ??????? ????Input: | ??????{ ????????"created_by": "eve25@tst.ibm.com", ????????"assigned_user_id": "51449f9b-a68f-059c-ad06-5039325c53b2", ????????"description": "2015-01-27 leads test", ????????"first_name": "one", ????????"last_name": "smith", ????????"phone_mobile": "22-222-2222", ????????... ??????} ??????? ??????? ????Response: | ??????{ ????????"my_favorite": false, ????????"following": false, ????????"id": "a260acfb-5b3e-3f74-2392-54d92387fb80", ????????"name": "one smith" ????????... ????????"_module": "Leads" ??????} |
在?/leads?API 部分的 HTTP?POST?方法中,我們使用了擴(kuò)展的屬性?x-sc-samples?和對?x-sc-samples?模式中的示例代碼?leads-post-create-lead?的 JSON 引用:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | paths: ?????? ??/leads: ????parameters: ??????- $ref: 'MASTER#/parameters/OAuthToken' ??????- $ref: 'MASTER#/parameters/ContentType' ??????? ????post: ??????summary: create lead ??????tags: [ leads ] ??????x-sc-APIm-plans: ????????- salesconnect_leads_create ????????? ??????description: | ????????<p>API to create a lead.</p> # # Use the x-sc-samples property to refer to samples of the usage # of the /leads API. # ??????x-sc-samples: ????????- $ref: '#/x-sc-samples/leads-post-create-lead' ????????- $ref: '#/x-sc-samples/leads-post-create-lead-employeecnum' ????????? ????????? ??????parameters: ????????- name: lead_definition ??????????in: body ??????????description: definition of lead to be created ??????????schema: ????????????$ref: '#/definitions/LeadObject' ????????????? ??????responses: ????????200: ??????????$ref: '#/responses/LeadObjectResponse' ??????????? ????????422: ??????????description: | ????????????<p>scenarios</li> ????????????<ul> ????????????<li>missing required field</li> ????????????<li> invalid values for optional fields</li> ????????????<li> et cetera</li> ????????????</ul> |
將定義和示例放在一起
為了將所有模塊定義和示例放在一起,我們使用了一個 MASTER.yaml 文件。此文件記錄了邏輯信息,包括 Swagger 版本、API 版本、總體信息和提供該 API 的相對基礎(chǔ)路徑(relative base path)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | swagger: '2.0' info: ??version: '3.4' ??title:? Sales Connect API # # ??description: > ????This is the SalesConnect API. ????<p> There are several modules, each with different top level path. ????Most of the modules follow the same general pattern for operations and results, ????varying in the Sales Connect object that is manipulated.</p> ????<p>? The individual module descriptions show ????the particular operations and any module specific details.</p> ?? # # basePath: /sales/test/salesconnect host: w3-dev.api.ibm.com |
此外,MASTER.yaml 還包含包、共享對象和模板的注解。
包
通過在 MASTER.yaml 文件中定義?package(包)和?package sets(包集)屬性,可以動態(tài)地生成內(nèi)容。一個?package(包)定義了與給定模塊相關(guān)的所有 YAML 文件,而?package set(包集)是對最終文檔中的內(nèi)容進(jìn)行精細(xì)控制的包的集合。在我們的示例中,?demo?和?default?包集分別從一組不同的文件中拉取內(nèi)容。結(jié)合使用包和包集,我們可以輕松地將已發(fā)布模塊與仍在開發(fā)中的模塊分開。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | x-sc-master:??? ??? ??packages: ????bulk: ????- modules/bulk ????? # # The oauth package contains 2 files: #?? - the modules/oauth.yaml file #?? - the samples/oauth-samples.yaml file #??? ????oauth: ????- modules/oauth ????- samples/oauth-samples ???????? ????calls: ????- modules/calls ????- samples/calls-samples ????? ????collab: ????- modules/collab ????? ????notes: ????- modules/notes ????- samples/notes-samples ????? ????... ????leads: ????- modules/leads ????- samples/leads-samples ????- samples/leadsTBD-samples ????... ????? ??package-sets: ??? # # When generating a "default" document, our tool pulls # content from files specified under the "oauth", "bulk", # "calls", "collab" and "notes" packages. # ????default: ??????- oauth ??????- bulk ??????- calls????? ??????- collab ??????- notes ?????? # # When generating a "demo" document, our tool pulls # in a different set of files. # ????demo: ??????- oauth ??????- notes ??????- leads |
共享對象
我們注意到,在實(shí)現(xiàn)過程中,反復(fù)提到了一些對象:多個 API 后端使用了相同的過濾器 URL 參數(shù),多個 API 的?GET?方法返回了一組相同的基本字段,而且 API Manager 為不同的調(diào)用返回了相同的錯誤消息格式。為了減少冗余,我們使用?BasicObject?屬性和?APImException?對象將這些元素提取到 MASTER.yaml 文件中,前者定義了所有 HTTP 方法?GET?API 返回的基本字段,后者描述了從 API Manager 返回的錯誤結(jié)構(gòu)。
使用模板
許多 API 的響應(yīng)都遵循類似的模式,所以我們設(shè)計了模板來減少重復(fù)和支持變體。例如,當(dāng)一個模塊鏈接到另一個模塊時,一些 API 的響應(yīng)將包含來自二者的對象。為了適應(yīng)這種情形,我們在 MASTER.yaml 文件中設(shè)計了一個?(OBJECT)Link(otherOBJECT)Response?模板:
| 1 2 3 4 5 6 7 8 9 10 11 | (OBJECT)Link(otherOBJECT)Response: ????description: | ??????Result of creating link from (OBJECT) to (otherOBJECT). ??????The record contains the (OBJECT) and the <em>related_record</em> the (otherOBJECT) objects. ????schema: ??????properties: ????????record: ??????????$ref: 'MASTER#/definitions/(OBJECT)' ????????????? ????????related_record: ??????????$ref: 'MASTER#/definitions/(otherOBJECT)' |
當(dāng)記錄一個將?Note?模塊?(OBJECT=NoteObject)?鏈接到?Account?模塊?(otherOBJECT=AccountObject)?的 API 的響應(yīng)時,可以采用以下格式:
| 1 2 3 4 5 6 7 | post: ??summary: Establish an accounts link to note using ccms id. ??description: Establish an accounts link to note using ccms id. ??responses: ????default: ??????$ref: 'MASTER?OBJECT=NoteObject&otherOBJECT=AccountObject#/responses/ (OBJECT)Link(otherOBJECT)Response' |
在我們的示例中,$ref?告訴該工具訪問 MASTER.yaml 文件并在?responses?模式下查找(OBJECT)Link(otherOBJECT)Response?對象。實(shí)例化 JSON 引用之前,該工具將?OBJECT?變量替換為?NoteObject,將?otherOBJECT?替換為?AccountObject。最終,該模板被擴(kuò)展為:
| 1 2 3 4 5 6 7 8 9 10 11 | NoteObjectLinkAccountObjectResponse: ????description: | ??????Result of creating link from NoteObject to AccountObject. ??????The record contains the NoteObject and the <em>related_record</em> the AccountObject objects. ????schema: ??????properties: ????????record: ??????????$ref: 'MASTER#/definitions/NoteObject' ?????????????? ????????related_record: ??????????$ref: 'MASTER#/definitions/AccountObject' |
類似地,您可以通過將?OBJECT?和?otherOBJECT?設(shè)置為不同的值,使用此模板來記錄將?Note?模塊鏈接到?Opportunity?模塊的 API 的響應(yīng):
| 1 2 3 4 5 6 7 8 9 | post: ??summary: Link from note to opportunity. ??description: Link from note to opportunity. ??x-sc-APIm-plans: [ salesconnect_notes_create ] ??responses: ????default: ??????$ref: 'MASTER?OBJECT=NoteObject&otherOBJECT=OpportunityObject#/responses/ (OBJECT)Link(otherOBJECT)Response' |
將 YAML 文檔轉(zhuǎn)換為 HTML 頁面
為了讓 API 文檔對用戶更友好,我們實(shí)現(xiàn)了一個工具(swagger-to-html.php)來將 YAML 文檔轉(zhuǎn)換為靜態(tài) HTML。盡管可以使用現(xiàn)有工具從 Swagger 構(gòu)建 HTML 文檔,但我們決定創(chuàng)建自己的工具,以便可以添加對?x-sc-*?擴(kuò)展的特殊處理功能。
該工具將會讀入 MASTER.yaml 文件,合并所有必要的 YAML 文件,解析引用,然后輸出一個 HTML 頁面。該工具接受許多不同的參數(shù),您可使用它們來自定義 HTML 文件的內(nèi)容。例如,您可以為特定模塊生成 HTML 文件,為特定包集生成 HTML 文件,或者僅為向 IBM API Management 應(yīng)用程序注冊的 API 生成 HTML 文件。
生成的 HTML 是單個文件,它使用 CSS 設(shè)置樣式,使用 JavaScript 自動化各個部分的折疊、展開和導(dǎo)航功能。HTML 生成器工具會呈現(xiàn)通用 JSON 對象、JSON 模式定義,以及參數(shù)、響應(yīng)、操作等的 Swagger 描述。
這是為?Lead?模塊中的?lead_source?項(xiàng)生成的 HTML 頁面(請參閱“擴(kuò)展屬性”部分的相應(yīng) YAML 文檔):
這是來自?/leads?API 端點(diǎn)的 HTTP?POST?方法的 HTML 頁面(請參閱“包含示例”部分的相應(yīng) YAML 文檔):
幕后原理
這個 API-swagger.zip 文件(參見“下載”)演示了我們的 Swagger API 文檔子集中針對?SalesConnect?系統(tǒng)中的三個模塊的部分:OAuth、Lead?和?Note。這些 API 位于 /modules 目錄中,相應(yīng)的示例包含在 /samples 目錄中。
要生成 HTML 頁面:
php tools/swagger-to-html.php?salesconnect.swagger/MASTER.yaml --set demo >c:/swagger/salesconnectAPI.html
php tools/swagger-to-html.php salesconnect.swagger/MASTER.yaml --modules oauth,leads > c:/swagger/salesconnectAPI.html
結(jié)束語
Swagger 是一個為 RESTful API 創(chuàng)建文檔的強(qiáng)大工具,而且通過實(shí)現(xiàn)自定義擴(kuò)展、工具和模板,您可以獲得對 Swagger 生成的文檔的格式和內(nèi)容的更多選擇和控制。通過擴(kuò)展 Swagger 的功能,您可以包含更多特定于 API 的細(xì)節(jié),指定 HTTP 請求和響應(yīng),并以 HTML 格式輸出文檔,以便開發(fā)人員和 API 使用者都可以閱讀。
下載資源
- 示例代碼?(API-swagger.zip | 83KB)
http://www.ibm.com/developerworks/cn/web/wa-use-swagger-to-document-and-define-restful-apis/index.html
?
總結(jié)
以上是生活随笔為你收集整理的使用 Swagger 文档化和定义 RESTful API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux基础命令的操作(时间与日期,日
- 下一篇: 2014百度研发真题及其解析-求比指定数