所有文章 > API开发 > 使用 OpenAPI 和 Prism 模拟回调
使用 OpenAPI 和 Prism 模拟回调

使用 OpenAPI 和 Prism 模拟回调

回调是服务为响应某个操作而向其他服务发出的传出异步请求。它们与 JavaScript 等流行编程语言中的回调函数非常相似。但它们是在 API 抽象级别执行的。

回拨在日常生活中随处可见,例如当您订购包裹时。如果您订阅更新,运送包裹的物流公司将向您发送有关事件的通知,例如:“您的包裹已准备好领取”、“您的包裹已到达最终目的地”。

这种类型的通信是异步且实时发生的。非常酷的东西!

其他方法

回调解决了异步通信问题。通常,执行计算密集型操作的系统使用 KafkaRabbitMQ 或基于 JMS 的消息队列。使用主题实现对事件的选择性订阅。但是,由于底层协议不是 Web 友好的(不是基于 HTTP),因此典型的 Web 应用程序无法利用这些解决方案。

另一种常见方法是使用配置 WebHooks。GitHub 或 Stripe 公开了一个用于设置它们的 UI。

我说过 WebHook 吗?简单解释一下:WebHook 是接收回调请求的调用方 API 端点。

这种解决方案的缺点是您需要使用 WebHook 的 URL 手动更新外部服务(如 GitHub)。这使您的配置变得分散,难以维护和更新。

为什么要回调

  • 它们在 OpenAPI 中是标准化的
  • 它是一个 Web 标准,意味着它被设计用于在基于 HTTP 的环境中安全地使用,通常是公开可用的(面向客户端)
  • 支持选择性数据订阅
  • 接收端点配置保留在调用方,这使其成为单一事实来源

如何使用 OpenAPI 和 Prism 设置回调

现在让我们设定一个目标。目标是模拟一个完整的、真实的回调命中 WebHook 的示例。我们将使用 Prism 作为模拟工具。

假设有一家名为 Ship-n-Pray Ltd. 的物流公司。作为该公司的合作伙伴,我们决定集成他们的 API 来自动化我们的流程。例如,当包裹到达时,我们希望向客户发送电子邮件。或者跟踪和统计物流公司的运营情况。

幸运的是,他们公开了一个 API,让我们可以跟踪这一点。此外,这是一个 OpenAPI 规范。我们正在与专业人士打交道!

Ship-n-Pray Ltd 的 API 的 OpenAPI 规范

logistics.oas3.yaml

openapi: 3.0.0
paths:
/tracking/{parcelId}/subscribe:
parameters:
- name: parcelId
in: path
required: true
description: The parcel identifier
schema:
$ref: '#/components/schemas/parcelId'
post:
summary: Subscribe to notifications about given parcel
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
format: uri
token:
type: string
required:
- url
- token
responses:
202:
description: 'Successfully subscribed to notifications about given parcel'
content:
text/plain:
examples:
ok:
value: 'ok'
callbacks:
notification:
'{$request.body#/url}?token={$request.body#/token}':
post:
summary: 'Receive single notification about a parcel'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/notification'
responses:
200:
description: 'Notification successfully processed'
content:
text/plain:
examples:
ok:
value: 'ok'
components:
schemas:
parcelId:
type: string
pattern: '^[0-9]{16}$'
notification:
type: object
properties:
parcelId:
$ref: "#/components/schemas/parcelId"
status:
type: string
enum:
- pick-up
- in-transit
- delivered
required:
- parcelId
- status

好吧,等一下,内容相当多。让我描述一下重要的几行。

1.我们将POST在端点执行请求/tracking/{parcelId}/subscribe,以便订阅有关 所标识的包裹的通知parcelId

注意: $ref: '#/components/schemas/parcelId'这是一个技巧,使我们能够重用parcelId模式定义(在文档末尾的组件部分中定义)

2.请求主体部分定义预期的输入负载:

  • url使您可以告诉物流公司您希望在哪个 URL 上接收通知
  • token是我们安全的基础。每次订阅都会生成令牌并存储在我们这边。在收到通知时,我们将验证令牌是否由我们生成。

注意: token 可能是随机生成的数据(我们需要将其存储在我们这边)。它也可能是公钥(那么我们只需要验证它是否与我们的秘密私钥匹配)。

requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
format: uri
token:
type: string
required:
- url
- token

3.接下来,responses部分定义单个202响应。202表示“接受”以供进一步处理。

最重要的部分: 。在我们的例子中,keywordcallbacks下的键是它们的名称。然后是标题 – 。此路径是运行时表达式。路径表示将从请求正文中提取并构建通知接收 URL。callbacksnotification'{$request.body#/url}?token={$request.body#/token}'urltoken

客户端服务的 OpenAPI 规范

client.oas3.yaml

openapi: 3.0.0
paths:
/notify:
post:
summary: 'Receive notification about a parcel'
security:
- TokenSecurity: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/notification'
responses:
'200':
description: 'Notification successfully processed'
content:
text/plain:
examples:
ok:
value: 'ok'
components:
securitySchemes:
TokenSecurty:
type: apiKey
name: token
in: query
schemas:
parcelId:
type: string
pattern: '^[0-9]{16}$'
notification:
type: object
properties:
parcelId:
$ref: "#/components/schemas/parcelId"
status:
type: string
enum:
- pick-up
- in-transit
- delivered
required:
- parcelId
- status

我们的 API 规范定义了一个处理通知接收的端点。就这么简单!

让我们模拟

我们已经定义了物流服务 API 和我们的 API 的规范。现在是时候启动prism实例并查看一些操作了。

下面的命令将为港口prism的物流公司运行实例4010

prism mock -p 4010 logistics.oas3.yaml

现在请打开新的控制台并运行以下命令:

prism mock -p 4011 client.oas3.yaml

准备好?

curl -v -H'Content-type: application/json' -d'{ "url": "http://localhost:4011/notify", "token": "dontpeek" }' http://127.0.0.1:4010/tracking/7352110771638879/subscribe

以下是物流服务的输出:

[CLI] …  awaiting  Starting Prism
[HTTP SERVER] info Server listening at http://127.0.0.1:4010
[CLI] info POST http://127.0.0.1:4010/tracking/7352110771638879/subscribe
[HTTP SERVER] post /tracking/7352110771638879/subscribe info Request received
[NEGOTIATOR] info Request contains an accept header: */*
[VALIDATOR] success The request passed the validation rules. Looking for the best response
[NEGOTIATOR] success Found a compatible content for */*
[NEGOTIATOR] success Responding with the requested status code 202
[CALLBACK] info notification: Making request to http://localhost:4011/notify?token=dontpeek...
[CALLBACK] info notification: Request finished

以及客户端服务控制台相应的输出:

[CLI] …  awaiting  Starting Prism
[HTTP SERVER] info Server listening at http://127.0.0.1:4011
[CLI] info POST http://127.0.0.1:4011/notify
[HTTP SERVER] post /notify info Request received
[NEGOTIATOR] info Request contains an accept header: */*
[VALIDATOR] success The request passed the validation rules. Looking for the best response
[NEGOTIATOR] success Found a compatible content for */*
[NEGOTIATOR] success Responding with the requested status code 200

哇哦!发生什么事了?

  1. 请求POST已提出http://127.0.0.1:4010/tracking/7352110771638879/subscribe
  2. Prism 回复202表示订阅已被接受。
  3. 请求体包含回调URL和token
  4. 回调定义包含有关如何构造 WebHook URL 的配方,这将导致http://localhost:4011/notify?token=dontpeek
  5. 发生 Parcel 事件,触发通知请求
  6. /notifyPrism使用模拟有效负载向我们的端点执行请求
  7. 客户端控制台显示已收到通知

对于那些喜欢图表的人来说,这里有一个序列图。它展示了订阅回调和接收三个通知的过程。

序列图

恭喜,您刚刚模拟了两个服务并强制它们相互通信。本教程到此结束!

那很好,但是我为什么需要 Prism?

测试回调可能会变得很复杂。你可能需要编写一些小工具来模拟调用者服务。或者用curl “手动”调用它。或者强制服务调用你的 API 并相信它确实会这样做。

听起来还挺简单的?现在想象一下你的 API 会随着时间而改变。你需要维护该工具,但你丢失了curl命令,而且没有关于如何快速测试 API 的文档。哦,多么熟悉啊!

但是,等一下,您有一个始终保持最新的 OpenAPI 规范(因为您的老板告诉您这样做),并且 Prism 可以将其变成 API 任何部分的功能齐全的模仿。现在您既不需要秘密命令,也不需要非文档化的工具。

原文链接:Mocking Callbacks with OpenAPI and Prism

#你可能也喜欢这些API文章!