API Gateway如何根据请求动态返回XML或JSON格式响应?
问题描述
我有一套基于Node.js的API Gateway服务栈和Node Lambda函数,想要实现API Gateway根据请求参数format(取值为xml或json),返回对应Content-Type为application/xml或application/json的响应。试过添加响应模型(response models)但没生效,配置BinaryTypes也没用,现在只能返回单一格式(当前示例始终返回application/json)。想知道这种动态切换响应格式的需求是否可行?还是必须创建两个独立的端点?
Lambda 函数代码
exports.handler = async function(event, context, callback) { var format = event.format; if (!format) { callback(Error("[BadRequest] missing parameters")); } const promise = new Promise(function(resolve, reject) { https .get("exampleendpoint.com", (res) => { let body = ""; res.on("data", (chunk) => { body += chunk; }); res.on("end", () => { var results = JSON.parse(body); if (format && format.toUpperCase() === "XML") { var response = { statusCode: 200, headers: { "content-type": "application/xml" }, body: '<?xml version="1.0" encoding="UTF-8"?><result>' + OBJtoXML(results) + "</result>", }; resolve(response); } else { var response = { statusCode: 200, headers: { "content-type": "application/json" }, body: JSON.stringify(results), }; resolve(response); } }); }) .on("error", (e) => { var response = { statusCode: 500, body: "", errorMessage: "Error from example.com", }; resolve(response); }); }); return promise; };
API Gateway CDK 配置代码
const epqApi = new gateway.RestApi(this, "restApi", { restApiName: "resultsApi", cloudWatchRole: true, description: "Calls the service for the app", endpointTypes: [gateway.EndpointType.REGIONAL], deployOptions: { stageName: "prod", loggingLevel: gateway.MethodLoggingLevel.OFF, dataTraceEnabled: false, }, }); const epqResource = epqApi.root.addResource("v1"); const epqIntegration: gateway.LambdaIntegration = new gateway.LambdaIntegration(generatePqsResultFunction, { proxy: false, allowTestInvoke: true, passthroughBehavior: gateway.PassthroughBehavior.NEVER, contentHandling: gateway.ContentHandling.CONVERT_TO_TEXT, requestTemplates: { "application/json": `{ "format":"$input.params('format')" }`, }, integrationResponses: [{ statusCode: "200", responseParameters: { "method.response.header.Access-Control-Allow-Origin": "'*'", }, responseTemplates: { "application/json": "$input.path('$.body')", "application/xml": "$input.path('$.body')", }, }, { statusCode: "400", selectionPattern: "^\\[BadRequest\\].*", responseParameters: { "method.response.header.Access-Control-Allow-Origin": "'*'", }, responseTemplates: { "application/javascript": "#set($inputRoot = $input.path('$')) {\"errorMessage\" : \"$input.path('$.errorMessage')\"}", }, }, ], }); epqResource.addMethod("GET", epqIntegration, { requestParameters: { //all params need to be in here, even if they are not required "method.request.querystring.x": false, "method.request.querystring.y": false, "method.request.querystring.units": false, "method.request.querystring.format": false, "method.request.querystring.wkid": false, "method.request.querystring.includeDate": false, }, methodResponses: [ // Successful response from the integration { statusCode: "200", responseParameters: { "method.response.header.Access-Control-Allow-Origin": true, }, }, { statusCode: "400", responseParameters: { "method.response.header.Access-Control-Allow-Origin": true, }, }, ], });
解决方案
这个需求完全可行,不需要创建两个独立端点。问题出在API Gateway配置未根据Lambda返回的格式标识动态匹配响应逻辑,以下是两种可行的解决方式:
方式一:优化API Gateway集成配置
关键调整步骤
Lambda返回添加格式标识
在Lambda的响应对象中新增format字段,方便API Gateway识别返回类型:// XML响应示例 var response = { statusCode: 200, headers: { "content-type": "application/xml" }, body: '<?xml version="1.0" encoding="UTF-8"?><result>' + OBJtoXML(results) + "</result>", format: "xml" }; // JSON响应示例 var response = { statusCode: 200, headers: { "content-type": "application/json" }, body: JSON.stringify(results), format: "json" };更新Method Responses配置
在200状态码中添加允许返回Content-Type头:methodResponses: [ { statusCode: "200", responseParameters: { "method.response.header.Access-Control-Allow-Origin": true, "method.response.header.Content-Type": true // 允许返回Content-Type头 }, }, // 保留400状态码配置 { statusCode: "400", responseParameters: { "method.response.header.Access-Control-Allow-Origin": true, }, }, ]拆分集成响应规则
为XML和JSON分别创建集成响应,通过selectionPattern匹配Lambda返回的format字段:integrationResponses: [ // JSON格式响应规则 { statusCode: "200", selectionPattern: '"format":"json"', responseParameters: { "method.response.header.Access-Control-Allow-Origin": "'*'", "method.response.header.Content-Type": "'application/json'" }, responseTemplates: { "application/json": "$input.path('$.body')" }, }, // XML格式响应规则 { statusCode: "200", selectionPattern: '"format":"xml"', responseParameters: { "method.response.header.Access-Control-Allow-Origin": "'*'", "method.response.header.Content-Type": "'application/xml'" }, responseTemplates: { "application/xml": "$input.path('$.body')" }, }, // 保留400错误响应配置 { statusCode: "400", selectionPattern: "^\\[BadRequest\\].*", responseParameters: { "method.response.header.Access-Control-Allow-Origin": "'*'", }, responseTemplates: { "application/javascript": "#set($inputRoot = $input.path('$')) {\"errorMessage\" : \"$input.path('$.errorMessage')\"}", }, }, ]
方式二:启用Lambda代理集成(更简单)
直接开启Lambda代理模式,让API Gateway完全透传Lambda返回的响应(包括Headers、Body、StatusCode),无需配置响应模板:
修改集成配置:
const epqIntegration: gateway.LambdaIntegration = new gateway.LambdaIntegration(generatePqsResultFunction, { proxy: true, // 开启代理模式 allowTestInvoke: true, });
这种模式下,动态切换格式的逻辑完全由Lambda处理,API Gateway不做额外转换,配置更简洁。
内容的提问来源于stack exchange,提问作者Jordan Parfitt
相关产品推荐
相关产品推荐

