跳至內容

回呼

在 OpenAPI 3 規格中,您可以定義回呼 – 您的服務將在回應特定事件時傳送給其他服務的非同步、頻外請求。這有助於您改善 API 提供給用戶端的運作流程。回呼的典型範例是訂閱功能 – 用戶訂閱您服務的某些事件,並在發生此事件或彼事件時收到通知。例如,電子商店可以在每次購買時向管理員傳送通知。這些通知將是「頻外」的,也就是說,它們將通過與訪客使用的連線不同的連線,並且它們將是非同步的,因為它們將脫離常規的請求-回應流程。在 OpenAPI 3 中,您可以定義「訂閱」操作的格式,以及回呼訊息的格式和這些訊息的預期回應。此描述將簡化不同伺服器之間的通訊,並協助您標準化 API 中 Webhook 的使用。

回呼範例

讓我們建立一個回呼定義 – 一個簡單的 Webhook 通知。假設您的 API 提供 POST /subscribe 操作,該操作預期請求主體中具有回呼 URL

1
POST /subscribe
2
Host: my.example.com
3
Content-Type: application/json
4
5
{
6
"callbackUrl": "https://myserver.com/send/callback/here"
7
}

API 確認訂閱 —

1
HTTP/1.1 201 Created

— 然後在發生特定事件時傳送通知

1
POST /send/callback/here
2
Host: myserver.com
3
Content-Type: application/json
4
5
{
6
"message": "Something happened"
7
}

現在讓我們定義 /subscribe 操作

1
openapi: 3.0.0
2
info:
3
version: 0.0.0
4
title: test
5
6
paths:
7
/subscribe:
8
post:
9
summary: Subscribe to a webhook
10
requestBody:
11
required: true
12
content:
13
application/json:
14
schema:
15
type: object
16
properties:
17
callbackUrl: # Callback URL
18
type: string
19
format: uri
20
example: https://myserver.com/send/callback/here
21
required:
22
- callbackUrl
23
responses:
24
"201":
25
description: Webhook created

現在讓我們將回呼關鍵字新增至此操作以定義回呼

1
paths:
2
/subscribe:
3
post:
4
summary: Subscribe to a webhook
5
requestBody:
6
callbacks: # Callback definition
7
myEvent: # Event name
8
"{$request.body#/callbackUrl}": # The callback URL,
9
# Refers to the passed URL
10
post:
11
requestBody: # Contents of the callback message
12
required: true
13
content:
14
application/json:
15
schema:
16
type: object
17
properties:
18
message:
19
type: string
20
example: Some event happened
21
required:
22
- message
23
responses: # Expected responses to the callback message
24
"200":
25
description: Your server returns this code if it accepts the callback

讓我們逐行瀏覽此定義

  • callbacks 是在相關操作 - postput 等 (而不是在路徑本身下) 中定義的。在本範例中,是在 /subscribe 路徑的 post 方法下
1
paths:
2
/subscribe:
3
post:
4
5
callbacks:
6

這並不表示 API 僅在此操作運作時才會傳送回呼。您的 API 會在您服務的業務邏輯需要時傳送回呼請求。關鍵字層級結構只是讓您可以使用 /subscribe 操作的參數來設定回呼請求 (請參閱下方)。

  • callbacks 內,我們定義一或多個回呼訊息。在我們的範例中,我們只有一個訊息。您可以在下方找到具有多個回呼的範例。每個回呼的定義都以事件名稱 (_myEvent_ 在我們的範例中) 開頭
1
callbacks:
2
myEvent: # Event name
  • 在事件名稱下,我們定義您的服務將傳送回呼訊息的 URL。在我們的範例中,URL 是使用 {$request.body#/callbackUrl} 表達式指定的
1
callbacks:
2
myEvent:
3
"{$request.body#/callbackUrl}": # The callback URL, refers to the URL passed in the request body

此表達式表示回呼 URL 將基於 /subscribe 操作的參數。我們稍後將詳細說明這些表達式。

  • 在 URL 下方,我們指定回呼訊息的方法,並定義訊息格式和預期的回應。這些定義類似於常規請求和回應定義
1
callbacks:
2
myEvent:
3
"{$request.body#/callbackUrl}":
4
post: # Method
5
requestBody: # Contents of the callback message
6
7
responses: # Expected responses
8

請注意,當您定義回呼時,您是在定義 API 的規格。回呼功能的實際實作是在伺服器程式碼中完成的。

使用執行階段表達式參照請求欄位

如您所見,在我們的範例中,我們使用 {$request.body#/callbackUrl} 表達式。它是執行階段表達式,設定在回呼中將使用 POST /subscribe 請求的哪些資料。執行階段表示與 API 端點不同,此 URL 並非預先得知,而是根據 API 用戶端提供的資料在執行階段評估的。此值會因用戶端而異。例如,POST /subscribe 請求可以如下所示

1
POST /subscribe?p1=query-param-value HTTP/1.1
2
Host: my.example.com
3
Content-Type: application/json
4
Content-Length: 187
5
6
{
7
"callbackUrl" : "http://my.client.com/callback"
8
}
9
10
201 Created
11
Location: http://my.example.com?id=123

您可以使用下列表達式來參照其資料

表達式範例描述
{$url}/subscribe父操作 URL。
{$method}POST回呼請求的方法。
{$request.path.eventType}myEvent事件名稱。
{$request.query.param-name}query-param-value ( p1 查詢參數)指定查詢參數的值。
{$request.header.header-name}application/json (Content-Type 標頭)「訂閱」請求的指定標頭。
{$request.body#/field-name}callbackUrl請求主體中的欄位。如果欄位是陣列,請使用類似 {$request.body#/arrayField/2} 的語法。
{$response.header.header-name}http://my.example.com?id=123 (Location 標頭)指定回應標頭的值(對「訂閱」請求的回應)。

您可以在回呼定義中結合執行階段表達式和靜態資料。例如,您可以用以下方式定義回呼 URL

1
{$request.body#callbackUrl}/data:
2
– or –
3
{$request.body#/callbackUrl}/{$request.query.eventType}:

您可以使用表達式來指定查詢參數

1
{$request.body#/callbackUrl}/data?p1={$request.query.eventType}

如果字串同時包含執行階段表達式和靜態文字,您應該將執行階段表達式括在大括號中。如果整個字串都是執行階段表達式,您可以省略大括號。

多個回呼

如上所述,您可以使用一個「訂閱」操作來定義多個回呼

1
/subscribe:
2
post:
3
requestBody:
4
content:
5
application/json:
6
schema:
7
type: object
8
properties:
9
inProgressUrl:
10
type: string
11
failedUrl:
12
type: string
13
successUrl:
14
type: string
15
responses:
16
"200":
17
description: OK
18
callbacks:
19
inProgress:
20
"{$request.body#/inProgressUrl}":
21
post:
22
requestBody:
23
$ref: "#/components/requestBodies/callbackMessage1"
24
responses:
25
"200":
26
description: OK
27
"{$request.body#/failedUrl}":
28
post:
29
requestBody:
30
$ref: "#/components/requestBodies/callbackMessage2"
31
responses:
32
"200":
33
description: OK
34
"{$request.body#/successUrl}":
35
post:
36
requestBody:
37
$ref: "#/components/requestBodies/callbackMessage3"
38
responses:
39
"200":
40
description: OK

取消訂閱回呼

您如何實作取消訂閱機制取決於您。例如,接收伺服器可以在回呼訊息的回應中返回特定代碼,以表示它不再對回呼感興趣。在這種情況下,客戶端只能在回應回呼請求時取消訂閱。為了讓客戶端可以隨時取消訂閱,您的 API 可以提供一個特殊的「取消訂閱」操作。這是一種相當常見的方法。在這種情況下,您的服務可以為每個訂閱者生成一個 ID 或權杖,並在對「訂閱」請求的回應中返回此 ID 或權杖。要取消訂閱,客戶端可以將此 ID 傳遞給「取消訂閱」操作,以指定要移除的訂閱者。以下範例示範如何在您的規範中定義此行為

1
paths:
2
/subscribe:
3
description: Add a subscriber
4
post:
5
parameters:
6
- name: callbackUrl
7
in: query
8
required: true
9
schema:
10
type: string
11
format: uri
12
- name: event
13
in: query
14
required: true
15
schema:
16
type: string
17
responses:
18
'201':
19
description: Added
20
content:
21
application/json:
22
type: object
23
properties:
24
subscriberId:
25
type: string
26
example: AAA-123-BBB-456
27
links: # Link the returned id with the unsubscribe operation
28
unsubscribeOp:
29
operationId: unsubscribeOperation
30
parameters:
31
Id: $response.body#/subscriberId
32
callbacks:
33
myEvent:
34
'{$request.query.callbackUrl}?event={$request.query.event}':
35
post:
36
requestBody:
37
content:
38
application/json:
39
example:
40
message: Some event
41
responses:
42
'200':
43
description: OK
44
45
/unsubscribe:
46
post:
47
operationId: unsubscribeOperation
48
parameters:
49
- name: Id
50
in: query
51
required: true
52
schema:
53
type: string

找不到您要找的內容嗎? 在社群中提問
發現錯誤了嗎? 請告訴我們