AWS CloudFormation如何定义一个接收XML的API Gateway和Lambda

6次阅读

必须使用API gateway rest api而非http API,因后者不支持requestTemplates和xml透传;需配置contentHandling: CONVERT_TO_TEXT、requestTemplates匹配application/xml,并确保Lambda直接解析原始XML字符串

AWS CloudFormation如何定义一个接收XML的API Gateway和Lambda

CloudFormation 本身不直接支持将 API Gateway 的 requestTemplates 设为 XML 解析模式(比如 application/xml),但可以通过显式配置 IntegrationRequestrequestTemplatescontentHandling 实现。关键在于:API Gateway v1(REST API)支持 XML,而 v2(HTTP API)**不支持 requestTemplates 或 XML passthrough** —— 必须用 REST API。

必须使用 REST API 而非 HTTP API

HTTP API 在 CloudFormation 中无法指定 requestTemplates,也没有 contentHandling: CONVERT_TO_TEXT 选项,因此无法可靠接收原始 XML 并透传给 Lambda。REST API 才是唯一可行路径。

  • AWS::ApiGateway::RestApi 是唯一能配置 XML 处理的资源类型
  • AWS::ApiGatewayV2::Api 不接受 requestTemplates,且其 payloadFormatVersion 只支持 "1.0""2.0",均不解析原始 XML body
  • 若误用 HTTP API,Lambda 收到的 Event.body 会是 base64 编码的字符串,且无明确方式还原原始 XML 结构(尤其含命名空间、DOCTYPE 等)

在 IntegrationRequest 中启用 CONVERT_TO_TEXT 并写 XML 模板

默认情况下,API Gateway 会尝试 jsON 化请求体;要保留原始 XML,必须设置 contentHandling: CONVERT_TO_TEXT,并用 requestTemplates$input.body 直接映射过去。

  • 模板中不能用 $input.json('$')(会失败),必须用 $input.body
  • requestTemplates 的 key 必须匹配 Content-Type 请求头,例如 "application/xml"
  • 务必设置 passthroughBehavior: WHEN_NO_MATCH,否则无匹配模板时会返回 500
{   "Type": "AWS::ApiGateway::Method",   "Properties": {     "RestApiId": {"Ref": "MyRestApi"},     "ResourceId": {"Ref": "MyResource"},     "HttpMethod": "POST",     "AuthorizationType": "NONE",     "Integration": {       "Type": "AWS_proxy",       "IntegrationHttpMethod": "POST",       "Uri": {"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambda.Arn}/invocations"},       "RequestTemplates": {         "application/xml": "$input.body"       },       "ContentHandling": "CONVERT_TO_TEXT",       "PassthroughBehavior": "WHEN_NO_MATCH"     }   } }

Lambda 函数需处理 raw String body(不是 JSON)

由于启用了 CONVERT_TO_TEXT,Lambda 的 event.body 是原始 XML 字符串(非 base64,也非 JSON 对象),可直接用标准 XML 解析器处理。

  • python 示例中应避免 json.loads(event['body']),改用 xml.etree.ElementTree.fromstring(event['body'])
  • node.js 中可用 new DOMParser().parseFromString(event.body, 'text/xml')fast-xml-parser
  • 注意:event.isBase64Encodedfalse,无需 Buffer.from(..., 'base64')
  • 前端未设 Content-Type: application/xml,API Gateway 会 fallback 到 WHEN_NO_MATCH 模板(如果没配则报错),所以 header 必须正确发送

部署后测试要点:Header、Encoding、Error Mapping

即使模板写对,实际调用仍可能失败,原因往往不在 CloudFormation 本身,而在请求细节或错误响应配置。

  • curl 测试时必须带 -H "Content-Type: application/xml",否则匹配不到模板
  • XML 内容若含 UTF-8 特殊字符,需确保请求 body 是 UTF-8 编码,且不额外添加 bom
  • MethodResponseIntegrationResponse 中,建议显式定义 application/xmlresponseTemplates,否则默认返回 JSON 格式错误(如 500 时)
  • CloudFormation 不校验 XML 模板语法,拼写错误(如 "applicaiton/xml")会导致请求 500 且日志里只显示 “No template found”

最易被忽略的是:REST API 的 Deployment 资源必须显式依赖 MethodResource,否则更新后 API 不生效;另外,Lambda 执行角色需有 lambda:InvokeFunction 权限,且 API Gateway 需已添加权限(通过 AWS::Lambda::Permission)。这些不是 XML 专属问题,但在调试 XML 流程时常常卡在这几步。

text=ZqhQzanResources