brew install oasdiff

oasdiff 包裝器

如果您想在不安裝任何東西的情況下嘗試一下,oasdiff 也有幾個包裝器。

2. 嘗試 oasdiff

安裝 oasdiff 后,您可以測試它以了解其工作原理。首先,確保您已克隆GitHub 存儲庫。完成后,您可以運行oasdiff diff以查看兩個本地 YAML 文件之間的差異。

輸入以下命令。

oasdiff diff data/openapi-test1.yaml data/openapi-test2.yaml

當你這樣做時,你應該得到以下輸出。

info:
contact:
added: true
version:
from: 1.0.0
to: 1.0.1
paths:
deleted:
- /subscribe
- /api/{domain}/{project}/install-command
- /register
modified:
/api/{domain}/{project}/badges/security-score:
operations:
added:
- POST
modified:
GET:
tags:
deleted:
- security
operationID:
from: GetSecurityScores
to: ""
parameters:
deleted:
cookie:
- test
header:
- user
- X-Auth-Name
modified:
path:
domain:
schema:
type:
from: string
to: integer
format:
from: hyphen-separated list
to: non-negative integer
description:
from: Hyphen-separated list of lowercase string
to: Non-negative integers (including zero)
example:
from: generic-bank
to: "100"
min:
from: null
to: 7
pattern:
from: ^(?:([a-z]+-)*([a-z]+)?)$
to: ^(?:\d+)$
query:
filter:
content:
mediaTypeModified:
application/json:
schema:
properties:
modified:
color:
type:
from: string
to: number
image:
explode:
from: null
to: true
schema:
description:
from: alphanumeric
to: alphanumeric with underscore, dash, period, slash and colon
examples:
deleted:
- "0"
token:
schema:
anyOf:
added:
- RevisionSchema[0]
- RevisionSchema[1]
type:
from: string
to: ""
format:
from: uuid
to: ""
description:
from: RFC 4122 UUID
to: ""
example:
from: 26734565-dbcc-449a-a370-0beaaf04b0e8
to: null
maxLength:
from: 29
to: null
pattern:
from: ^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12})$
to: ""
responses:
added:
- default
deleted:
- "200"
- "201"
- "400"
parameters:
deleted:
path:
- domain
endpoints:
added:
- method: POST
path: /api/{domain}/{project}/badges/security-score
deleted:
- method: POST
path: /register
- method: POST
path: /subscribe
- method: GET
path: /api/{domain}/{project}/install-command
modified:
? method: GET
path: /api/{domain}/{project}/badges/security-score
: tags:
deleted:
- security
operationID:
from: GetSecurityScores
to: ""
parameters:
deleted:
cookie:
- test
header:
- user
- X-Auth-Name
modified:
path:
domain:
schema:
type:
from: string
to: integer
format:
from: hyphen-separated list
to: non-negative integer
description:
from: Hyphen-separated list of lowercase string
to: Non-negative integers (including zero)
example:
from: generic-bank
to: "100"
min:
from: null
to: 7
pattern:
from: ^(?:([a-z]+-)*([a-z]+)?)$
to: ^(?:\d+)$
query:
filter:
content:
mediaTypeModified:
application/json:
schema:
properties:
modified:
color:
type:
from: string
to: number
image:
explode:
from: null
to: true
schema:
description:
from: alphanumeric
to: alphanumeric with underscore, dash, period, slash and colon
examples:
deleted:
- "0"
token:
schema:
anyOf:
added:
- RevisionSchema[0]
- RevisionSchema[1]
type:
from: string
to: ""
format:
from: uuid
to: ""
description:
from: RFC 4122 UUID
to: ""
example:
from: 26734565-dbcc-449a-a370-0beaaf04b0e8
to: null
maxLength:
from: 29
to: null
pattern:
from: ^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12})$
to: ""
responses:
added:
- default
deleted:
- "200"
- "201"
- "400"
security:
deleted:
- bearerAuth
servers:
deleted:
- tufin.com
tags:
deleted:
- security
- reuven
externalDocs:
deleted: true
components:
schemas:
deleted:
- network-policies
- rules
parameters:
deleted:
- network-policies
headers:
deleted:
- testc
- new
- test
requestBodies:
deleted:
- reuven
responses:
deleted:
- OK
securitySchemes:
deleted:
- AccessToken
- OAuth
- bearerAuth

如您所見,oasdiff 的輸出非常詳細地描述了兩個版本之間發生的所有修訂。例如,本例中刪除了以下端點:/subscribe/api/{domain}/{project}/install-command/register

在該modified部分下,您可以看到端點/api/{domain}/{project}/badges/security-score:已添加 POST 命令。此外,許多功能也已被棄用,這些功能也已詳細說明。

如果您想要更整潔的列表,也可以將結果返回為 HTML。不要使用-f text字符串末尾的命令,而是使用-f html,如下所示。

oasdiff diff data/openapi-test1.yaml data/openapi-test2.yaml -f html

Oasdiff 不僅適用于本地文件。您還可以使用 HTTP/s 輕松查看遠程 API 之間的差異。

首先輸入以下內容:

oasdiff diff https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml -f text

結果顯示,四個端點已被修改:security-scoreinstall-commandregistersubscribe

如果您想查看兩個版本之間的任何重大變化,請嘗試以下步驟:

oasdiff breaking https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml

這些結果表明,將端點中的成功狀態替換為200或會導致中斷。201security-score

甚至還有一個專門的命令用于評估/API路徑內的端點。

oasdiff diff https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test1.yaml https://raw.githubusercontent.com/Tufin/oasdiff/main/data/openapi-test3.yaml -f text -p "/api"

您還可以排除端點。您可以使用該–match-path命令過濾路徑名,以過濾掉與特定表達式不匹配的路徑。您還可以使用該–filter-extension命令過濾掉特定的擴展名。

3. 將 oasdiff 集成到 Go 項目中

使用 oasdiff 的最大原因之一是集成到自動化工作流程中。如果您使用 Go 進行開發,則可以在代碼中直接使用 oasdiff。只需使用以下命令:

diff.Get(&diff.Config{}, spec1, spec2)

下面是 Go 程序中 oasdiff 的一個示例。

loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true

s1, err := loader.LoadFromFile("../data/simple1.yaml")
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load spec with %v", err)
return
}

s2, err := loader.LoadFromFile("../data/simple2.yaml")
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load spec with %v", err)
return
}

diffReport, err := diff.Get(diff.NewConfig(), s1, s2)

if err != nil {
fmt.Fprintf(os.Stderr, "diff failed with %v", err)
return
}

bytes, err := yaml.Marshal(diffReport)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to marshal result with %v", err)
return
}
fmt.Printf("%s\n", bytes)

返回以下輸出:

aths:
modified:
/api/test:
operations:
added:
- POST
deleted:
- GET
endpoints:
added:
- method: POST
path: /api/test
deleted:
- method: GET
path: /api/test
``

您還可以使用 oasdiff 來檢測代碼內部的重大變化。

package main

import (
"fmt"
"os"
"strings"

"github.com/getkin/kin-openapi/openapi3"
"github.com/tufin/oasdiff/checker"
"github.com/tufin/oasdiff/diff"
"github.com/tufin/oasdiff/load"
)

func main() {
loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true

s1, err := load.LoadSpecInfo(loader, load.NewSource("../data/openapi-test1.yaml"))
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load spec with %v", err)
return
}

s2, err := load.LoadSpecInfo(loader, load.NewSource("../data/openapi-test3.yaml"))
if err != nil {
fmt.Fprintf(os.Stderr, "failed to load spec with %v", err)
return
}

diffConfig := diff.NewConfig().WithCheckBreaking()

diffRes, operationsSources, err := diff.GetPathsDiff(diffConfig,
[]*load.SpecInfo{s1},
[]*load.SpecInfo{s2},
)

if err != nil {
fmt.Fprintf(os.Stderr, "diff failed with %v", err)
return
}

errs := checker.CheckBackwardCompatibility(checker.GetDefaultChecks(), diffRes, operationsSources)

// process configuration file for ignoring errors
errs, err = checker.ProcessIgnoredBackwardCompatibilityErrors(checker.ERR, errs, "../data/ignore-err-example.txt", checker.NewDefaultLocalizer())
if err != nil {
fmt.Fprintf(os.Stderr, "ignore errors failed with %v", err)
return
}

// process configuration file for ignoring warnings
errs, err = checker.ProcessIgnoredBackwardCompatibilityErrors(checker.WARN, errs, "../data/ignore-warn-example.txt", checker.NewDefaultLocalizer())
if err != nil {
fmt.Fprintf(os.Stderr, "ignore warnings failed with %v", err)
return
}

// pretty print breaking changes errors
if len(errs) > 0 {
localizer := checker.NewDefaultLocalizer()
count := errs.GetLevelCount()
fmt.Print(localizer("total-errors", len(errs), count[checker.ERR], "error", count[checker.WARN], "warning"))
for _, bcerr := range errs {
fmt.Printf("%s\n\n", strings.TrimRight(bcerr.SingleLineError(localizer, checker.ColorNever), " "))
}
}

}

返回:

4 breaking changes: 1 error, 3 warning
error at ../data/openapi-test3.yaml, in API GET /api/{domain}/{project}/badges/security-score removed the success response with the status '201' [response-success-status-removed].

warning at ../data/openapi-test3.yaml, in API GET /api/{domain}/{project}/badges/security-score deleted the 'cookie' request parameter 'test' [request-parameter-removed].

warning at ../data/openapi-test3.yaml, in API GET /api/{domain}/{project}/badges/security-score deleted the 'header' request parameter 'user' [request-parameter-removed].

warning at ../data/openapi-test3.yaml, in API GET /api/{domain}/{project}/badges/security-score deleted the 'query' request parameter 'filter' [request-parameter-removed].

關于 oasdiff 的最終想法

隨著 API 為軟件行業提供更多動力,API 版本控制將變得越來越普遍。無論如何,區分兩個版本只是 oasdiff 的潛在用途之一。能夠檢測到重大更改(尤其是在發生之前)更是將 oasdiff 集成到您的工作流程中的理由。幾行代碼就可以防止您和您的客戶出現服務中斷和意外停機。

文章來源:Using oasdiff to Detect Breaking Changes in APIs

上一篇:

API 在音樂產業中的作用

下一篇:

11 個期貨數據 API
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費