我正在尝试在 HTTP API 中创建一个端点,定期从远程设备接收数据。该项目发生了技术转变,设备之前以 XML 格式报告数据,而未来的实现将转向 JSON。
我正在使用 NestJS (7.x) 和 TypeScript 编写此 API。数据将通过相同的端点 ( ) 传入POST /,并且数据格式由标头区分Content-Type。
@Controller()
export class IngressController {
constructor(private readonly ingressService: IngressService) {
}
/* ... */
@Post('')
@Header('Cache-Control', 'none')
@HttpCode(HttpStatus.NO_CONTENT)
public async receive(
@Headers('Content-Type') contentType: string,
@Req() req: any,
@Body() body: string,
): Promise<InsertResponse> {
if (IngressController.isJson(contentType)) {
return { inserted: await this.ingressService.insertJsonString(req.body) };
}
if (IngressController.isXml(contentType)) {
return { inserted: await this.ingressService.insertXmlString(req.body) };
}
throw new BadRequestException(contentType, 'Unsupported Content-Type');
}
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
未来的设备将以 JSON 格式报告数据(由Content-Type: application/jsonHTTP 请求中的标头指示),而传统设备将以 XML ( Content-Type: application/xml) 格式报告数据。
它对于 JSON 来说效果非常好。然而,我的问题是req.body(或body分别)在 XML 情况下是一个空对象。我猜想 NestJS 中间件正在做一些事情并被 XML 搞糊涂了,但我没有发现任何关于允许 XML 有效负载与 JSON 并排的提示。我不介意手动解析它。
正如您怀疑的那样,NestJS 有一个内置的 bodyparser,它将无法解析 xml。您可以做的是插入一个自定义中间件,您可以在其中决定是将请求正文解析为 xml 还是将请求传递到下一个处理程序。
像这样的东西应该可以工作(我express-xml-bodyparser在这个例子中使用):
import {NestFactory} from '@nestjs/core';
import {AppModule} from './app.module';
import {Request} from "express";
const xmlParser = require('express-xml-bodyparser');
const xmlParserMidleware = xmlParser();
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use((req: Request, res: any, next: any) => {
if (req.path.includes("/api/json-or-xml-handler") && req.header('Content-Type')?.includes('xml')) {
return xmlParserMidleware(req, res, next);
}
next();
});
await app.listen(8020);
}
bootstrap();
Run Code Online (Sandbox Code Playgroud)
然后,在你的控制器中将body是解析后的 json 对象或 xml 的对象表示:
@Controller()
export class TestControllerController {
@Post('/api/json-or-xml-handler')
receive(@Body() body: any) {
console.log(body);
// ...
}
}
Run Code Online (Sandbox Code Playgroud)