如何将ApiGatewayV2请求头映射到SQS消息?
我使用.NET 6.0、CDK v2和ApiGatewayV2.Alpha,尝试将API Gateway的消息直接发送到SQS队列,因该版本无现成集成,自行实现了HttpSqsSendIntegration。现在需要将请求中的一个Header映射为SQS消息属性,按如下方式配置后始终出现400错误,错误信息为:
"Unable to resolve property MessageAttributes from source {"Signature":{"DataType":"String","StringValue":"$request.header.signature"}}. Please make sure that the request to API Gateway contains all the necessary fields specified in request parameters"
请问是否可以将请求头映射到SQS消息?若可以,该如何实现?
自定义集成代码
using System.Diagnostics.CodeAnalysis; using Amazon.CDK.AWS.Apigatewayv2.Alpha; using Amazon.CDK.AWS.IAM; using Amazon.CDK.AWS.SQS; using Constructs; namespace Infrastructure; public class HttpSqsSendIntegration : HttpRouteIntegration { private readonly Queue _queue; private readonly HttpSqsSendIntegrationProps? _props; private readonly Role _role; public HttpSqsSendIntegration(Construct scope, string id, Queue queue, HttpSqsSendIntegrationProps? props = null) : base(id) { ArgumentNullException.ThrowIfNull(queue); ArgumentNullException.ThrowIfNull(scope); _queue = queue; _props = props; _role = new Role(scope, "HTTP-API-SQS-Role", new RoleProps { AssumedBy = new ServicePrincipal("apigateway.amazonaws.com"), InlinePolicies = new Dictionary<string, PolicyDocument> { { "sqs-send", new PolicyDocument(new PolicyDocumentProps { Statements = [ new PolicyStatement(new PolicyStatementProps { Actions = [ "sqs:SendMessage" ], Resources = [ queue.QueueArn ], Effect = Effect.ALLOW }) ] }) } } }); } public override IHttpRouteIntegrationConfig Bind(IHttpRouteIntegrationBindOptions options) { var paramMapping = new ParameterMapping() .Custom("QueueUrl", _queue.QueueUrl) .Custom("MessageBody", _props?.MessageBody ?? "$request.body"); if (!string.IsNullOrWhiteSpace(_props?.MessageAttributes)) { paramMapping.Custom("MessageAttributes", _props.MessageAttributes); } return new HttpRouteIntegrationConfig { Type = HttpIntegrationType.AWS_PROXY, Subtype = HttpIntegrationSubtype.SQS_SEND_MESSAGE, PayloadFormatVersion = PayloadFormatVersion.VERSION_1_0, ParameterMapping = paramMapping, Credentials = IntegrationCredentials.FromRole(_role) }; } } public class HttpSqsSendIntegrationProps { public string? MessageBody { get; init; } public string? MessageAttributes { get; init; } public string[] Headers { get; init; } }
路由配置代码
var route = new HttpRoute(this, "HttpRoute", new HttpRouteProps { HttpApi = Framework.ApiGateway.Api, RouteKey = HttpRouteKey.With("/webhooks/{platform}/{webhook}", HttpMethod.POST), Integration = new HttpSqsSendIntegration(this, "SqsRouteIntegration", queue, new HttpSqsSendIntegrationProps { MessageAttributes = "{\"Signature\":{\"DataType\":\"String\",\"StringValue\":\"$request.header.signature\"}}" }) });
解决方案
可以将请求头映射到SQS消息属性,问题出在参数映射的格式解析逻辑上:API Gateway的参数映射不支持直接传递预转义的JSON字符串作为Custom参数值,需改用Velocity模板语法来动态构建符合要求的MessageAttributes结构。
正确实现方式
修改集成类的参数映射逻辑
去掉预转义的JSON格式,直接用Velocity模板语法构建消息属性字符串,确保变量$request.header.signature能被API Gateway正确解析:public override IHttpRouteIntegrationConfig Bind(IHttpRouteIntegrationBindOptions options) { var paramMapping = new ParameterMapping() .Custom("QueueUrl", _queue.QueueUrl) .Custom("MessageBody", _props?.MessageBody ?? "$request.body"); // 直接使用Velocity模板构建MessageAttributes,避免预转义 var messageAttrs = "{\"Signature\":{\"DataType\":\"String\",\"StringValue\":\"$request.header.signature\"}}"; paramMapping.Custom("MessageAttributes", messageAttrs); return new HttpRouteIntegrationConfig { Type = HttpIntegrationType.AWS_PROXY, Subtype = HttpIntegrationSubtype.SQS_SEND_MESSAGE, PayloadFormatVersion = PayloadFormatVersion.VERSION_1_0, ParameterMapping = paramMapping, Credentials = IntegrationCredentials.FromRole(_role) }; }路由配置保持不变
原路由配置中传递的MessageAttributes值格式是正确的,无需修改,确保请求中确实携带了signature请求头即可。关键注意事项
- 必须确保请求携带
signature请求头,否则API Gateway会因变量未定义抛出解析错误 - 保留
PayloadFormatVersion.VERSION_1_0,这是SQS集成要求的负载格式版本 - 确认IAM角色已正确配置
sqs:SendMessage权限
- 必须确保请求携带
内容的提问来源于stack exchange,提问作者Tom

