跳至内容

回调

在 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 在相关操作内定义 - post, put 等(不在路径本身下)。 在此示例中,在 /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-valuep1 查询参数)指定查询参数的值。
{$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

没有找到您想要的内容? 在社区提问
发现错误? 请告诉我们