无法从 API 网关向 SNS 主题发送大负载
Unable to send large payload to SNS topic from API Gateway
我已经实现了一个 API 网关端点,它在新请求到来时向 SNS 主题发送消息。通常,除了我尝试向 SNS 主题发送大量有效负载的情况外,它工作得很好。在这种情况下,即使我没有超过 SNS 或 API 网关限制和配额,我也会收到来自 SNS API 的错误请求。
例如,如果我将发送下一个包含 15k 个字母 'a' 的有效负载,或者如果数组将包含大约 8k 个整数,我将收到此消息:
{
"count": 1,
"data": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... .",
"flag": 1,
"arr": 1
}
据我所知,这种行为的原因隐藏在我的 CloudFormation 模板的下一行代码中:
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${some-topic-arn}'"
根据 documentation 我们可以使用 body 类型而不是 querystring 但它不起作用。
此外,我尝试使用请求模板映射并通过查询字符串发送 topicArn 并通过模板映射发送消息。但它也不起作用。
那么谁能告诉我我做错了什么以及如何解决通过 HTTP POST 请求发送大负载时收到错误请求错误的问题?
这是我当前的 CloudFormation 模板:
/v1/someApiEndpoint:
post:
请求正文:
内容:
application/json:
模式:
$ref: "#/components/schemas/SomeApiModel"
要求:真实
回应:
'200':
描述:“200响应”
....
'500':
description: "500 response"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
x-amazon-apigateway-request-validator: "SomeApiModelValidator"
x-amazon-apigateway-integration:
type: "aws"
httpMethod: "POST"
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:action/Publish"
credentials: !GetAtt SomeApiRole.Arn
responses:
'2\d{2}':
statusCode: 200
requestParameters:
integration.request.header.Content-Type: "'application/x-www-form-urlencoded'"
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${SomeTopicArn}'"
passthroughBehavior: "NEVER"
requestTemplates:
application/json: |
#set($input.path('$').payload = { "userIdentity": $util.parseJson($context.authorizer.userIdentity), "data": $util.parseJson($input.body) })
#set($encodedJson = $util.urlEncode($input.json('$.payload')))
这是我发送到 API 网关然后传输到 SNS 主题的模型定义:
class SomeApiModel
{
int count;
string data;
int flag;
int[] arr;
}
好的,我明白了。
经过许多小时的调查,我终于找到了问题并解决了它。
正如 Michael-sqlbot in the next 所提到的,我们需要覆盖 SNS 发布端点的路径。
顺便说一句,谢谢你救了我的命 =)
如果有人也会遇到这个问题,这里有一个解决方案:
- 首先。将 URI 属性 替换为 x-amazon-apigateway-integration: 部分:
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:action/Publish"`
对此:
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:path//"
它将覆盖路径为
- 从集成请求参数部分删除接下来的两行代码:
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${SomeTopicArn}'"
- 将 TopicArn、Message 和 Action 参数放入正文请求模板中:
请求模板:
application/json:
!Sub Action=Publish&TopicArn=$util.urlEncode('${my-topic-arn}')&Message=$util.urlEncode($input.body)##
这是此集成的完整 CloudFormation 模板定义:
x-amazon-apigateway-integration:
type: "aws"
httpMethod: "POST"
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:path//"
credentials: !GetAtt my-personal-role.Arn
responses:
'2\d{2}':
statusCode: 200
requestParameters:
integration.request.header.Content-Type: "'application/x-www-form-urlencoded'"
passthroughBehavior: "NEVER"
requestTemplates:
application/json:
!Sub Action=Publish&TopicArn=$util.urlEncode('${my-topic-arn}')&Message=$util.urlEncode($input.body)##
注意 Content-Type 属性。它应该被单引号括起来作为一个单词。
我已经实现了一个 API 网关端点,它在新请求到来时向 SNS 主题发送消息。通常,除了我尝试向 SNS 主题发送大量有效负载的情况外,它工作得很好。在这种情况下,即使我没有超过 SNS 或 API 网关限制和配额,我也会收到来自 SNS API 的错误请求。 例如,如果我将发送下一个包含 15k 个字母 'a' 的有效负载,或者如果数组将包含大约 8k 个整数,我将收到此消息:
{ "count": 1, "data": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... .", "flag": 1, "arr": 1 }
据我所知,这种行为的原因隐藏在我的 CloudFormation 模板的下一行代码中:
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${some-topic-arn}'"
根据 documentation 我们可以使用 body 类型而不是 querystring 但它不起作用。 此外,我尝试使用请求模板映射并通过查询字符串发送 topicArn 并通过模板映射发送消息。但它也不起作用。
那么谁能告诉我我做错了什么以及如何解决通过 HTTP POST 请求发送大负载时收到错误请求错误的问题?
这是我当前的 CloudFormation 模板: /v1/someApiEndpoint: post: 请求正文: 内容: application/json: 模式: $ref: "#/components/schemas/SomeApiModel" 要求:真实 回应: '200': 描述:“200响应” ....
'500':
description: "500 response"
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorMessage"
x-amazon-apigateway-request-validator: "SomeApiModelValidator"
x-amazon-apigateway-integration:
type: "aws"
httpMethod: "POST"
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:action/Publish"
credentials: !GetAtt SomeApiRole.Arn
responses:
'2\d{2}':
statusCode: 200
requestParameters:
integration.request.header.Content-Type: "'application/x-www-form-urlencoded'"
integration.request.querystring.Message: "method.request.body"
integration.request.querystring.TopicArn: !Sub "'${SomeTopicArn}'"
passthroughBehavior: "NEVER"
requestTemplates:
application/json: |
#set($input.path('$').payload = { "userIdentity": $util.parseJson($context.authorizer.userIdentity), "data": $util.parseJson($input.body) })
#set($encodedJson = $util.urlEncode($input.json('$.payload')))
这是我发送到 API 网关然后传输到 SNS 主题的模型定义:
class SomeApiModel
{
int count;
string data;
int flag;
int[] arr;
}
好的,我明白了。
经过许多小时的调查,我终于找到了问题并解决了它。
正如 Michael-sqlbot in the next
如果有人也会遇到这个问题,这里有一个解决方案:
- 首先。将 URI 属性 替换为 x-amazon-apigateway-integration: 部分:
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:action/Publish"`
对此:
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:path//"
它将覆盖路径为
- 从集成请求参数部分删除接下来的两行代码:
integration.request.querystring.Message: "method.request.body" integration.request.querystring.TopicArn: !Sub "'${SomeTopicArn}'"
- 将 TopicArn、Message 和 Action 参数放入正文请求模板中: 请求模板:
application/json: !Sub Action=Publish&TopicArn=$util.urlEncode('${my-topic-arn}')&Message=$util.urlEncode($input.body)##
这是此集成的完整 CloudFormation 模板定义:
x-amazon-apigateway-integration:
type: "aws"
httpMethod: "POST"
uri: !Sub "arn:aws:apigateway:${AWS::Region}:sns:path//"
credentials: !GetAtt my-personal-role.Arn
responses:
'2\d{2}':
statusCode: 200
requestParameters:
integration.request.header.Content-Type: "'application/x-www-form-urlencoded'"
passthroughBehavior: "NEVER"
requestTemplates:
application/json:
!Sub Action=Publish&TopicArn=$util.urlEncode('${my-topic-arn}')&Message=$util.urlEncode($input.body)##
注意 Content-Type 属性。它应该被单引号括起来作为一个单词。