使用 swagger 和自动生成的 php 客户端处理分块 json 响应的正确方法是什么?
What's the right way to handle chunked json response with swagger and autogenerated php client?
我在定义、生成的代码和许多有点像黑盒子的东西之间有点不知所措,即使在调试之后也是如此。
但让我们从头开始。我有一个 API 使用 NestJS 作为框架用节点编写的。 NestJS 自动创建 swagger/openapi json 文件。使用 swagger-codegen 我创建了一个 PHP class 来从另一台服务器访问 API 。对于简单的 API 请求来说就像一个魅力。
现在的问题是 API 请求返回更大的响应,即来自一个或多个数据库的 >1000 行。不要让客户端等待很长时间,并在我切换到 NDJSON 的服务器上创建一个大的 JSON 响应,它将响应分成更小的 JSON 部分的块,每个在它自己的线上。当我使用 fopen 和 fread 在 PHP 中使用 curl 或 HTTP 包装器手动创建请求时,这也有效。响应类型为 application/x-ndjson.
但是 swagger-codegen 生成的代码总是在等待,直到收到整个响应。更糟糕的是,因为它无法用 json_decode() 解码 NDJSON 并且只是 returns null。下面使用 Guzzle,它使用 PSR7 流进行响应。
现在我可以跳过 NDJSON 端点的自动生成代码。但我不想添加特殊处理并丢失所有有用的生成检查。
那么是否可以通过某种方式让 swagger-codegen 访问响应流?我是否缺少 codegen 的参数或 swagger JSON 中的某些参数?它确实有 application/x-ndjson.
的产品
回答我自己的问题是可能的,但并不容易 - 这意味着没有选项或参数。
首先创建一个 class 来扩展自动生成的 API class。在那里您可以访问所有受保护的方法。我们假设端点或 api 方法被称为 testMethodGet
。唯一可以重用的是请求方法,即 testMethodGetRequest
,但它完成了所有客户端验证和输入数据的转换,所以这已经是一个巨大的胜利。还要获得一些样板结果验证,您可以复制“http 信息方法”,即 testMethodGetWithHttpInfo
(如果您愿意,可以使用异步版本)。删除 $responseBody = $response->getBody();
之后的 if/else 块,并在 return 中将 ObjectSearializer 行替换为 $responseBody
.
你现在得到的是 PSR7 流的主体,但还有最后一个问题。默认情况下,整个响应被排空到一个临时文件中。要在创建的方法中真正从服务器流式传输结果主体,请向 $options 添加一个选项:$options['stream'] = true;
现在,一旦主体启动,方法 returns。无需等待全身内容。
还有一件事。由于结果是一个 PSR7 流,如果您更喜欢使用普通的文件和流方法,您可以使用 $stream->detach()
来获取 PHP 流资源。
我在定义、生成的代码和许多有点像黑盒子的东西之间有点不知所措,即使在调试之后也是如此。
但让我们从头开始。我有一个 API 使用 NestJS 作为框架用节点编写的。 NestJS 自动创建 swagger/openapi json 文件。使用 swagger-codegen 我创建了一个 PHP class 来从另一台服务器访问 API 。对于简单的 API 请求来说就像一个魅力。
现在的问题是 API 请求返回更大的响应,即来自一个或多个数据库的 >1000 行。不要让客户端等待很长时间,并在我切换到 NDJSON 的服务器上创建一个大的 JSON 响应,它将响应分成更小的 JSON 部分的块,每个在它自己的线上。当我使用 fopen 和 fread 在 PHP 中使用 curl 或 HTTP 包装器手动创建请求时,这也有效。响应类型为 application/x-ndjson.
但是 swagger-codegen 生成的代码总是在等待,直到收到整个响应。更糟糕的是,因为它无法用 json_decode() 解码 NDJSON 并且只是 returns null。下面使用 Guzzle,它使用 PSR7 流进行响应。
现在我可以跳过 NDJSON 端点的自动生成代码。但我不想添加特殊处理并丢失所有有用的生成检查。
那么是否可以通过某种方式让 swagger-codegen 访问响应流?我是否缺少 codegen 的参数或 swagger JSON 中的某些参数?它确实有 application/x-ndjson.
的产品回答我自己的问题是可能的,但并不容易 - 这意味着没有选项或参数。
首先创建一个 class 来扩展自动生成的 API class。在那里您可以访问所有受保护的方法。我们假设端点或 api 方法被称为 testMethodGet
。唯一可以重用的是请求方法,即 testMethodGetRequest
,但它完成了所有客户端验证和输入数据的转换,所以这已经是一个巨大的胜利。还要获得一些样板结果验证,您可以复制“http 信息方法”,即 testMethodGetWithHttpInfo
(如果您愿意,可以使用异步版本)。删除 $responseBody = $response->getBody();
之后的 if/else 块,并在 return 中将 ObjectSearializer 行替换为 $responseBody
.
你现在得到的是 PSR7 流的主体,但还有最后一个问题。默认情况下,整个响应被排空到一个临时文件中。要在创建的方法中真正从服务器流式传输结果主体,请向 $options 添加一个选项:$options['stream'] = true;
现在,一旦主体启动,方法 returns。无需等待全身内容。
还有一件事。由于结果是一个 PSR7 流,如果您更喜欢使用普通的文件和流方法,您可以使用 $stream->detach()
来获取 PHP 流资源。