You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS API Gateway VTL合并Lambda Authorizer的principalId至Event Bridge负载报错

解决API Gateway请求模板中EventBridge Detail格式错误问题

问题描述

需要将Lambda Authorizer返回的principalId合并到发送给EventBridge的负载中,当前通过转换为Map并重建JSON对象的方式实现,但生成的JSON键名无引号,导致EventBridge返回MalformedDetail错误。API Gateway的Velocity模板不支持AppSync的$util.toJson()方法,需寻找替代方案。

相关CDK代码

const eventsAPI = new RestApi(this, 'eventsAPI', apigwOps);

const LambdaAuth0Authorizer = new LambdaAuth0Authorizer(this, 'LambdaAuth0Authorizer', {
  env: {
    auth0Audience: '',
    auth0Domain: '',
  },
});

const eventTypeResource = eventsAPI.root.addResource('event');
const options: IntegrationOptions = {
  credentialsRole: apigwRole,
  passthroughBehavior: PassthroughBehavior.NEVER,
  requestParameters: {
    'integration.request.header.X-Amz-Target': "'AWSEvents.PutEvents'",
    'integration.request.header.Content-Type': "'application/x-amz-json-1.1'",
  },

  requestTemplates: {
    'application/json': `
    #set ( $map = $util.parseJson($input.body) )
    #set ( $j = {
      "eventType": "$map['eventType']",
      "action": "$map['action']",
      "subject": "$map['subject']",
      "eventTime": $map['eventTime'],
      "actor": "$context.authorizer.principalId"
     } 
    )
                {"Entries": 
                      [
                        {
                          "Source": "com.xyz", 
                          "Detail": "$util.escapeJavascript($j)", 
                          "Resources": [], 
                          "DetailType": "event", 
                          "EventBusName": "${eventBus.eventBusName}"
                        }
                      ]
                    }
      `,
  },
  integrationResponses: [
    {
      statusCode: '200',
      responseTemplates: {
        'application/json': '',
      },
    },
  ],
};
eventTypeResource.addMethod('POST', new Integration({
  type: IntegrationType.AWS,
  uri: `arn:aws:apigateway:${env.region}:events:path//`,
  integrationHttpMethod: 'POST',
  options: options,
}), {
  authorizer: LambdaAuth0Authorizer.authorizer,
  methodResponses: [{ statusCode: '200' }],
  requestModels: { 'application/json': getEventModel(this, eventsAPI) },
  requestValidator: new RequestValidator(this, 'eventValidator', {
    restApi: eventsAPI,
    validateRequestBody: true,
  }),
});

生成的错误请求内容

{"Entries": 
  [
    {
      "Source": "com.uproarapi", 
      "Detail": "{eventType=FOLLOW, action=CREATE, subject=USER_777POIUY, eventTime=51644444444, actor=}", 
      "Resources": [], 
      "DetailType": "UpRoarEvent", 
      "EventBusName": "UpRoarEventBus"
    }
  ]
}

返回的错误信息

{"Entries":[{"ErrorCode":"MalformedDetail","ErrorMessage":"Detail is malformed."}],"FailedEntryCount":1}

解决方案

问题根源在于Velocity模板中直接引用Map对象$j时,会输出Java对象的默认字符串形式(键名无引号),而非标准JSON。我们可以通过手动构建符合JSON规范的Detail字符串来解决:

修改请求模板中的application/json部分为以下内容:

#set ( $map = $util.parseJson($input.body) )
{
  "Entries": [
    {
      "Source": "com.xyz", 
      "Detail": "{\"eventType\":\"$util.escapeJavaScript($map.eventType)\",\"action\":\"$util.escapeJavaScript($map.action)\",\"subject\":\"$util.escapeJavaScript($map.subject)\",\"eventTime\":$map.eventTime,\"actor\":\"$util.escapeJavaScript($context.authorizer.principalId)\"}", 
      "Resources": [], 
      "DetailType": "event", 
      "EventBusName": "${eventBus.eventBusName}"
    }
  ]
}

关键修改说明

  • 直接拼接Detail的JSON字符串,所有键名用双引号包裹,符合JSON格式要求
  • 对字符串类型的字段(eventType、action等)使用$util.escapeJavaScript()处理,避免特殊字符(如引号、反斜杠)破坏JSON结构
  • 数值类型的eventTime保持无引号,与原输入格式一致

修改后生成的Detail会是标准JSON字符串,示例如下:

"Detail": "{\"eventType\":\"FOLLOW\",\"action\":\"CREATE\",\"subject\":\"USER_777POIUY\",\"eventTime\":51644444444,\"actor\":\"auth0-user-id\"}"

这样EventBridge就能正确解析Detail内容,不会再抛出格式错误。

内容的提问来源于stack exchange,提问作者Esteban Rincon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:01:19