介紹:
OAS就是定義基于http的遠(yuǎn)程api的文檔的一種規(guī)范
什么是API? API就是應(yīng)用程序接口接口,比如說像編程中調(diào)用到的方法/函數(shù),就是api之一,這個(gè)時(shí)候api是由方法的名稱、參數(shù)、返回值等組成的。對(duì)于本地api來說,交互雙方(調(diào)用者和提供api者)是處于同一臺(tái)機(jī)器的,比如你自己機(jī)器的標(biāo)準(zhǔn)c庫是由c編譯器程序提供的。
而OAS就是聚焦于遠(yuǎn)程API的描述的,一般來說,提供API服務(wù)的一方稱為提供方,而調(diào)用API的一方稱為消費(fèi)者。
OAS的優(yōu)點(diǎn):
文檔校驗(yàn)和檢查;
數(shù)據(jù)校驗(yàn);
文檔生成;
代碼自動(dòng)生成;
mock服務(wù);
安全分析;
同時(shí)可供機(jī)器和人類閱讀;
-
強(qiáng)大而完善的工具體系
使用 API 是計(jì)算機(jī)科學(xué)中的日常實(shí)踐,因?yàn)樗鼈兊暮锰幨俏阌怪靡傻摹?舉個(gè)最突出的例子:
API 提供信息隱藏:API 的任何一方(提供者和消費(fèi)者)都不知道另一方的實(shí)現(xiàn)細(xì)節(jié)。 只要兩者都遵守 API,就可以根據(jù)需要隨意更改,而對(duì)方甚至不會(huì)注意到。
API 也稱為契約,因?yàn)樗鼈儽徽J(rèn)為是牢不可破的:提供者承諾不會(huì)改變其 API 并在未來幾年繼續(xù)兌現(xiàn)它。 有了這個(gè)承諾,消費(fèi)者就可以開始開發(fā)他們的部件并充滿信心地依賴 API 提供的功能。
現(xiàn)在,為了讓所有相關(guān)方遵守相同的 API,必須對(duì)其進(jìn)行精確定義。 下一節(jié)將介紹傳統(tǒng)上如何實(shí)現(xiàn)這一目標(biāo)。
一般來說,API都會(huì)配套有參考指南,用于解釋如何來使用該api。而不幸地是,每個(gè)軟件開發(fā)者或許都會(huì)面臨以下的幾種情況: 不熟悉文檔
文檔不全
過時(shí)的信息
讀者無法理解的語言
為了解決這些問題,程序開發(fā)者往往需要大量時(shí)間來閱讀源碼、調(diào)試程序或者分析網(wǎng)絡(luò)流量,這太浪費(fèi)時(shí)間了
更現(xiàn)實(shí)的情況是,很多使用中會(huì)出現(xiàn)的問題,在你真真使用之前都難以發(fā)現(xiàn)
api描述文件(也稱為契約)是一種機(jī)器可讀的api規(guī)范(需要配合一些支持oas的工具,比如swagger)。它應(yīng)該是盡可能完整且詳細(xì)的(就是你幾乎盡可能地把這個(gè)api涉及到細(xì)節(jié)都給描述出來了,從url到請(qǐng)求參數(shù)、響應(yīng)參數(shù)、content-type、cookie、其他用到的header、以及包括對(duì)這些內(nèi)容的描述、字段類型啥的全都給說清楚),雖然這不是強(qiáng)制(如果把一切都寫清楚也不太現(xiàn)實(shí))。這就是合同/契約 一樣,你要是描述的越?jīng)]有歧義,那它就越有用。
跟一般的人類可讀的文檔相比(也就是以往開發(fā)人員自行手寫的比如markdown或者其他形式的文檔),它最大的優(yōu)勢(shì)就是可以由機(jī)器自動(dòng)處理,為本指南開頭列出的好處敞開了大門。
只要是按照OAS編寫的api描述,就可以很簡單利用工具生成面向人類可讀的文檔;更進(jìn)一步地說,它還能利用api描述直接生成即時(shí)可用的目標(biāo)代碼,這樣生成的客戶端代碼是完全匹配api描述的,也避免了我們手動(dòng)編寫代碼集成的時(shí)候一些錯(cuò)誤。
OAS解釋:
我們?cè)俅蝸斫榻B下OAS,OpenAPI規(guī)范(OAS)是一種與供應(yīng)商無關(guān)的基于http的遠(yuǎn)程api描述格式。它最初基于2015年SmartBear Software捐贈(zèng)的Swagger 2.0規(guī)范。
總而言之,它就是用于定義和描述基于http或者基于類似http的遠(yuǎn)程api的一種規(guī)范。
OAS規(guī)范:
整個(gè)OPENAPI的規(guī)范是很長的,對(duì)于新手來說是令人生畏的
所以我們需要先按主題、組織,簡化瀏覽
OpenAPI文檔結(jié)構(gòu):
OpenAPI文檔是一個(gè)文本文件,一般是xxx.json或者xxx.yaml,是以json或者yaml格式來書寫的
該文件被稱為根文檔并且可以被分割為多個(gè)json或者yaml文件 以讓其更加清晰
一般來說,JSON不支持注釋,需要:用逗號(hào)分隔字段,對(duì)象周圍用花括號(hào)括起來,字符串周圍用雙引號(hào)括 起來,數(shù)組周圍用方括號(hào)括起來。另一方面,YAML在數(shù)組項(xiàng)之前需要連字符,并且嚴(yán)重依賴縮進(jìn),這在大文件中可能很麻煩(在JSON中縮進(jìn)完全是可選的)。YAML通常是首選的,因?yàn)樗晕p小了文件大小,但是這兩種格式是完全可以互換的(只要使用YAML 1.2)。這些頁面中的所有示例都將在YAML中給出。
然而,YAML是JSON的超集,這意味著這兩種語法可以混合使用。雖然一般情況下不推薦這樣做,但有時(shí)還是會(huì)派上用場(chǎng)的。例如

最小結(jié)構(gòu)中info 和openapi字段是必須的,此外paths,components,webhooks這3個(gè)字段中也必須有至少的其中一個(gè)存在

接著簡單介紹下3個(gè)字段,openapi,info,paths
openapi:這個(gè)用來指示當(dāng)前api文檔所采用的OAS的版本
-
info:這個(gè)用來指示當(dāng)前api的版本以及當(dāng)前api的其他信息,注意這里指的當(dāng)前我們自己寫的api的信息,要注意它和openapi這個(gè)規(guī)范的版本有所不同
image.png paths,這個(gè)用于指示當(dāng)前api的所有端點(diǎn),包括他們的參數(shù)以及所有可能的服務(wù)器響應(yīng)。在自動(dòng)生成服務(wù)器和客戶端代碼的時(shí)候主要就是依據(jù)這里的描述了,按照這個(gè)思路,我們可以寫一個(gè)最小結(jié)構(gòu)的符合OAS的文檔出來
openapi: 3.1.0
info:
title: test
version: 0.0.1
paths: {}
OpenAPI端點(diǎn)endpoints
api端點(diǎn)在OAS中就是上面剛剛提到的paths對(duì)象

paths:需要注意的是paths字段的值是個(gè)對(duì)象,而不是一個(gè)數(shù)組,其中每個(gè)字段的鍵是端點(diǎn)名字,值是一個(gè) 路徑項(xiàng)對(duì)象,就像這樣:
paths: {
"/users": {路徑項(xiàng)對(duì)象},
"/posts": {路徑項(xiàng)對(duì)象}
}
路徑都必須以 / 開頭,為什么paths對(duì)象要采用對(duì)象而不是數(shù)組,是因?yàn)檫@樣可以更加明顯地表示paths對(duì)象中的端點(diǎn)名稱是唯一的
path item object:路徑項(xiàng)對(duì)象也是一個(gè)對(duì)象,其中的字段名是允許的http操作方法(get post put delete ...),值是一個(gè)操作對(duì)象(operation object), 需要注意的是在路徑項(xiàng)對(duì)象上還可以指定所有操作都接收的公共屬性,比如summary,description,比如
paths: {
"/users": {
"get": {操作對(duì)象},
"summary": "這是所有操作公共的摘要信息,當(dāng)然要是個(gè)別操作有不同的話,也可以單獨(dú)在該操作對(duì)象中指定"
},
"/posts": {路徑項(xiàng)對(duì)象}
}
operation object操作對(duì)象,除了summary和description以外,操作對(duì)象一般來說還會(huì)描述操作的參數(shù)、載荷、可能的服務(wù)器響應(yīng)等 paths:
/board:
get:
summary: Get the whole board
description: Retrieves the current state of the board and the winner.
parameters:
...
responses:
...
responses object響應(yīng)對(duì)象集合,注意這里還是responses,帶了個(gè)s,這個(gè)字段在操作對(duì)象中
用描述該操作有可能的各種服務(wù)器會(huì)給出的回答。這個(gè)對(duì)象中,每個(gè)字段的名字都是一個(gè)用引號(hào)括起來的http狀態(tài)碼,而它對(duì)應(yīng)的值就是一個(gè)響應(yīng)對(duì)象response object(注意這里沒有帶s了),進(jìn)而描述每個(gè)響應(yīng)對(duì)象的細(xì)節(jié),注意,在responses object中至少要指定一個(gè)狀態(tài)碼,并且最好是一個(gè)表示成功的狀態(tài)碼,比如200.
response object響應(yīng)對(duì)象,這里就是描述一個(gè)操作對(duì)象中具體的狀態(tài)碼對(duì)應(yīng)的返回信息了,
這個(gè)對(duì)象中必須要有一個(gè)description,用于對(duì)該響應(yīng)對(duì)象以及該狀態(tài)碼進(jìn)行補(bǔ)充描述(本質(zhì)上應(yīng)該就是通用http狀態(tài)碼描述)
body of message:
上一步最后展示的是api端點(diǎn)中的響應(yīng)對(duì)象,它位于操作對(duì)象中,實(shí)際上,在操作對(duì)象中除了description和responses以外,當(dāng)然還有很多其他字段,比如還有request body object,跟響應(yīng)對(duì)象相對(duì)應(yīng),它是請(qǐng)求對(duì)象。這里來介紹下在請(qǐng)求和響應(yīng)對(duì)象中都會(huì)用到的一個(gè)字段: content,內(nèi)容對(duì)象

content字段:它是標(biāo)準(zhǔn)媒體類型和OpenAPI媒體對(duì)象(OpenAPI Media Type Object)之間的映射對(duì),比如:
responses: {
"200": {
content: {
"application/json": {OpenAPI媒體對(duì)象},
"test/html": {OpenAPI媒體對(duì)象}
}
}
}
這意味著,可以根據(jù)不同的格式來返回內(nèi)容
Media Type Object媒體類型對(duì)象: 媒體類型對(duì)象就是一個(gè)媒體類型對(duì)應(yīng)著的具體的內(nèi)容結(jié)構(gòu),比如:
content:
application/json:
schema:
...
schema object模式對(duì)象: 模式對(duì)象用于定義數(shù)據(jù)類型,其可以是原子類型(整數(shù),字符串),數(shù)組或者對(duì)象,取決于其中的type字段,注意,當(dāng)schema的content位于responses就是定義的響應(yīng)數(shù)據(jù),當(dāng)位于request body object中,就是定義的請(qǐng)求數(shù)據(jù)
注意,對(duì)于我們平時(shí)開發(fā)的json 格式的api來說的,一般content中的schema肯定都是object,因?yàn)槲覀兌际欠祷匾粋€(gè)對(duì)象,比如

這就是我們平時(shí)接口返回的一個(gè)典型例子,對(duì)于這種情況,我們應(yīng)該將schema設(shè)置為object,然后再在object中進(jìn)一步定義其下的各個(gè)字段
這里介紹各個(gè)數(shù)據(jù)類型的定義要求:
在schema對(duì)象中,通過type字段定義數(shù)據(jù)類型,type是一個(gè)字符串,可用的值為:number,string,boolean,array,object,根據(jù)type字段的值,會(huì)有一些配套的其他字段用于擴(kuò)充定義
比如:對(duì)于string類型,就可以附加minLength和maxLength用于指定字符長度
對(duì)于integer類型,minimum和maximum字段可以用于指定最大最小值。
無論什么類型的值,都可以通過enum字段來限制該字段的值必須在它規(guī)定的范圍內(nèi),enum是數(shù)組
對(duì)于數(shù)組類型,必須指定items字段,它也是一個(gè)schema對(duì)象,通過它來定義數(shù)組中的每個(gè)元素的類型。除此之外,數(shù)組的長度可以通過minItems和maxItems字段來指定
最后,對(duì)于對(duì)象類型的字段,必須通過properties字段來指定對(duì)象中的屬性,properties是一個(gè)對(duì)象,其中的鍵是字段名,值是schema對(duì)象
content:
application/json:
schema:
type: object
properties:
productName:
type: string
productPrice:
type: number
parameters和requestBody
OAS提供了兩種機(jī)制來指定輸入數(shù)據(jù),parameters和request body(消息體).parameters用于標(biāo)識(shí)資源,request body用于提供資源的內(nèi)容

parameter對(duì)象: 在路徑項(xiàng)對(duì)象和操作對(duì)象中的parameters字段是一個(gè)包含parameter對(duì)象的數(shù)組,當(dāng)在路徑項(xiàng)對(duì)象中提供時(shí),parameters是與那一個(gè)路徑下的所有操作對(duì)象共享的
每一個(gè)parameter對(duì)象描述一個(gè)參數(shù),使用如下必須的字段:
- in(string): 參數(shù)所處的位置
可選值: - path,也就是說是位于路徑的一部分,也就是說我們?cè)谥付窂降臅r(shí)候,可以將路徑的一部分通過參數(shù)來代指,比如說路徑其實(shí)可以這樣指定, /users/{id} ,而且如果這樣指定了路徑的話,那么久必須通過parameter中的對(duì)應(yīng)一個(gè)名為id的參數(shù)來指定,同時(shí)需要注意的是,如果是路徑參數(shù)的話,那么該parameter對(duì)象中,必須有required: true 這一對(duì)屬性值
- query: 就是附加在url的?后面的參數(shù)值
- header: 作為自定義的HTTP header部分,注意它的名稱是大小寫敏感的
name(string):參數(shù)名字,區(qū)分大小寫,在每個(gè)位置中必須唯一
額外的可選字段:
description:描述信息,required(boolean)是否必填
parameter type:
大多時(shí)候,指定參數(shù)的數(shù)據(jù)類型都是通過schema對(duì)象(也就是在parameter對(duì)象中的schema字段)來指定。schema對(duì)象允許定義原子或者復(fù)雜的數(shù)據(jù)類型(數(shù)組或者對(duì)象)
parameters:
-
name: id
in: query
schema:
type: integer
minimum: 1
maximum: 100
在更高級(jí)的場(chǎng)景中,會(huì)通過content字段來指定字段類型,它提供一個(gè)單入口(媒體類型到OAS媒體類型的)的映射。注意:schema或者content二者必須存在其一。它們不能同時(shí)出現(xiàn)
request body object:請(qǐng)求體是通過在操作對(duì)象中的requestBody字段來指定的,唯一的必填字段就是content
components和$ref
復(fù)用描述,很常見的情況是文檔太大以致于不好管理。為此我們可以通過復(fù)用機(jī)制來移除冗余的部分。
components對(duì)象:通過在根節(jié)點(diǎn)下的components字段定義,包含了要復(fù)用的對(duì)象的定義

當(dāng)然,并非所有的對(duì)象都是可以復(fù)用的,只有那些作為components對(duì)象的字段才可以列出來,比如schemas,responses,parameters
組件對(duì)象中的每個(gè)字段都是一個(gè)將組件名稱與要重用的對(duì)象配對(duì)的映射。這些對(duì)象的類型必須與父字段匹配,例如,模式映射中的對(duì)象必須是模式對(duì)象;responses映射中的對(duì)象必須是response對(duì)象
引用對(duì)象:任意一個(gè)Components對(duì)象中的OpenAPI對(duì)象都可以通過引用對(duì)象來代替。
引用對(duì)象:通過 "$ref": "指向引用對(duì)象的uri資源路徑",來使用
提供示例: example和examples
api服務(wù)器servers:
servers對(duì)象提供了API的基礎(chǔ)URL,通過servers字段來定義,它是一個(gè)數(shù)組,它可以存在于根節(jié)點(diǎn)、路徑項(xiàng)對(duì)象或者操作對(duì)象中。

servers是一個(gè)數(shù)組,其中的每一個(gè)元素就是一個(gè)server對(duì)象,至少要有一個(gè)url字段,用于表示基礎(chǔ)路徑。一個(gè)可選的description字段,當(dāng)不同層級(jí)都有指定servers時(shí),只有層級(jí)最低的那一級(jí)會(huì)生效。例如:
servers:
- url: https://server1.com
paths:
/users:
get:
servers:
- url: https://server2.com
```yaml
/users這個(gè)路徑實(shí)際應(yīng)該是追加在server2后面的,完整的請(qǐng)求url是 [https://server2.com](https://server2.com)/users
server url中可以包含變量,在url中通過{}分隔,這些變量必須在進(jìn)一步在server對(duì)象的variables中進(jìn)行配置。variables是一個(gè)對(duì)象,它是一個(gè)變量名和變量對(duì)象之間的映射關(guān)系。
服務(wù)器變量對(duì)象有以下字段:
default(string): 這是一個(gè)必填字段,如果沒有其他值要提供的話
enum(字符串?dāng)?shù)組):如果存在的話,那么這個(gè)數(shù)組就會(huì)列出該變量的合法值,默認(rèn)值也必須出現(xiàn)在其中
description: 該字段的描述
