如何将 API Gateway REST API 与 Amazon SQS 集成并解决常见错误?

4 分钟阅读
0

我想将 Amazon API Gateway REST API 与 Amazon Simple Queue Service(Amazon SQS)集成,并对集成错误进行故障排除。

解决方法

要将 API Gateway REST API 与 Amazon SQS 集成,请选择以下方法之一:

使用 AWS 查询协议

要将 API Gateway REST API 与 Amazon SQS 集成,您可以使用 AWS 查询协议。为此,请完成以下步骤:

  1. 创建 SQS 队列
  2. 创建 AWS Identity and Access Management(IAM)角色,然后附加具有 SendMessage 权限的 Amazon SQS 策略。该政策允许您从 API 向 Amazon SQS 发布消息:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
      ],
      "Action": [
        "sqs:SendMessage"
      ]
    }
  ]
}

**注意:**将 example-region 替换为您的 AWS 区域,将 example-account-id 替换为您的 AWS 账户 ID,将 example-sqs-queue-name 替换为您的 SQS 队列名称。

  1. 在 API Gateway 中创建 REST API
  2. API Gateway 控制台中,为您的 REST API 创建 Amazon SQS 集成。
  3. 创建 REST API 资源或 REST API 方法
    资源界面,选择创建方法
    对于方法类型,选择 POST
    对于集成类型,选择 AWS 服务
    对于 AWS 区域,选择您的区域。
    对于 AWS 服务,选择 Simple Queue Service(SQS)
    (可选)对于 AWS 子域,输入 AWS 服务使用的子域。查看 AWS 产品文档,确认子域是否可用。对于 Amazon SQS 示例设置,请将其留空。
    对于 HTTP 方法,选择 POST
    对于操作类型,选择使用路径覆盖
    对于路径覆盖(可选),请按以下格式输入您的账户 ID 和 SQS 队列名称:example-account-id/example-sqs-queue-name。例如: 1234567890/MySQSStandardQueue
    对于执行角色,输入 IAM 角色的 ARN。
    默认超时中,为您的设置选择一个选项。
    继续输入您的 REST API 集成信息。
    选择 POST 方法集成请求
    选择编辑
    对于请求正文传递,请选择符合您要求的选项。
    展开 URL 请求标头参数
    选择添加请求标头参数
    名称中,输入 Content-Type
    对于映射自,输入 'application/x-www-form-urlencoded'
    展开映射模板
    选择 Add mapping template(添加映射模板)。
    对于 Content-Type,输入 application/json
    对于模板,输入 Action=SendMessage&MessageBody=$input.body,然后选择保存
  4. 部署 REST API
  5. 要测试这个设置,请向 API Gateway 发送以下请求:
curl --location --request POST 'https://example-api-id.execute-api.example-region.amazonaws.com/example-stage/example-resource' \  
   --header 'Content-Type: application/json' \  
   --data-raw '{  
    "message": "Hello World"  
  }'

**注意:**将 example-api-id 替换为您的 API ID,将 example-region 替换为您的区域,将 example-stage 替换为您的测试阶段名称,将 example-resource 替换为您的资源名称。

成功集成后,您将看到如下所示的回复:

{  
  "SendMessageResponse": {  
    "ResponseMetadata": {  
      "RequestId": "f879fb11-e736-52c0-bd29-a0f2d09ad90d"  
    },  
      "SendMessageResult": {  
        "MD5OfMessageAttributes": null,  
        "MD5OfMessageBody": "3fc759ac1733366f98ec4270c788fcd1",  
        "MD5OfMessageSystemAttributes": null,  
        "MessageId": "4c360c3c-08f4-4392-bc14-8b0c88e314a2",  
        "SequenceNumber": null  
    }  
  }  
}

使用 AWS JSON 协议

要将 API Gateway REST API 与 Amazon SQS 集成,您可以使用 AWS JSON 协议。为此,请完成以下步骤:

  1. 创建 SQS 队列
  2. 创建 AWS IAM 角色,然后附加具有 SendMessage 权限的 Amazon SQS 策略。该策略允许您从 API 向 Amazon SQS 发布消息:
{  
  "Version": "2012-10-17",  
  "Statement": [  
    {  
      "Effect": "Allow",  
      "Resource": [  
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"  
      ],  
      "Action": [  
        "sqs:SendMessage"  
      ]  
    }  
  ]  
}

**注意:**将 example-region 替换为您的 AWS 区域,将 example-account-id 替换为您的 AWS 账户 ID,将 example-sqs-queue-name 替换为您的 SQS 队列名称。

  1. 在 API Gateway 中创建 REST API
  2. API Gateway 控制台中,为您的 REST API 创建 Amazon SQS 集成。
  3. 创建 REST API 资源或 REST API 方法
    资源界面,选择创建方法
    对于方法类型,选择 POST
    对于集成类型,选择 AWS 服务
    对于 AWS 区域,选择您的区域。
    对于 AWS 服务,选择 Simple Queue Service(SQS)
    对于 AWS 子域,请将其留空。这是一个可选参数,您可以在其中输入 AWS 服务使用的子域。查看 AWS 产品文档,确认子域是否可用。
    对于 HTTP 方法,选择 POST
    对于操作类型,选择使用路径覆盖
    对于路径覆盖,请输入 / 字符。
    对于执行角色,输入 IAM 角色的 ARN。
    默认超时中,为您的设置选择一个选项。
    展开 HTTP 请求标头
    选择添加标题
    名称中,输入 Content-Type
    选择添加标题
    名称中,输入 X-Amz-Target
    选择创建方法
    选择 POST 方法集成请求
    选择编辑
    对于请求正文传递当没有模板与请求内容类型标头匹配时,保留为默认选项。
    展开 URL 请求标头参数
    选择添加请求标头参数
    名称中,输入 Content-Type
    对于映射来源,输入 method.request.header.Content-Type
    选择添加请求标头参数
    名称中,输入 X-Amz-Target
    对于映射来源,输入method.request.header.X-Amz-Target
    选择保存
  4. 部署 REST API
  5. 要测试这个设置,请向 API Gateway 发送以下请求:
curl --location --request POST 'https://example-api-id.execute-api.example-region.amazonaws.com/example-stage/example-resource' \
  --header 'Content-Type:application/x-amz-json-1.0' \
  --header 'X-Amz-Target:AmazonSQS.SendMessage' \
  --data-raw '{
    "QueueUrl": "https://sqs.<region>.<domain>/<awsAccountId>/<queueName>/",
    "MessageBody": "This is a test message"
}'

**注意:**将 example-api-id 替换为您的 API ID,将 example-region 替换为您的区域,将 example-stage 替换为您的测试阶段名称,将 example-resource 替换为您的资源名称。要查找您的 QueueUrl 值,请查看您的 Amazon SQS 队列详细信息。

如果集成成功,则您将看到如下所示的回复:

{"MD5OfMessageBody":"fafb00f5732ab283681e124bf8747ed1","MessageId":"b5aef1f3-af31-49f2-9973-6f802f7753e6"}

**注意:**AWS JSON 协议的预期响应与 AWS 查询协议不同,即使是相同的 API 调用也是如此。有关每个协议的响应示例,请参阅 SQS API 参考

解决常见错误

UnknownOperationException 错误

AWS 查询协议和 AWS JSON 协议都可能出现 UnknownOperationException 错误。

如果您使用 AWS 查询协议,则当您没有在集成请求 HTTP 标头中将 Content-Type 配置为 "application/x-www-form-urlencoded" 时,会出现 UnknownOperationException 错误。当您没有将 SendMessage 操作添加到集成请求的映射模板时,也会出现此错误。要解决此错误,请确保 Content-Type 格式正确,并在映射模板中包含 SendMessage 操作。

如果您使用 AWS JSON 协议,则当您没有发送或未正确配置 Content-TypeX-Amz-Target 标头时,就会出现 UnknownOperationException 错误。要解决此错误,请将 Content-Type 标头配置为 "application/x-amz-json-1.0",并将 X-Amz-Target 标头配置为 AmazonSQS.{SQS-Action},并在请求中包含两个标头。

AccessDenied 错误

AWS 查询协议和 AWS JSON 协议都可能出现 AccessDenied 错误。

当 API 集成执行角色未拥有向 SQS 队列发送消息的 sqs:SendMessage 权限时,会出现 AccessDenied 错误。

当您使用 AWS 查询协议并在请求正文有效载荷字符串中传递不支持的特殊字符时,也会出现此错误。必须对特殊字符进行编码以避免此错误。在映射模板中添加 $util.urlEncode() 函数,将请求正文从字符串转换为编码格式。以下是映射模板示例:

Action=SendMessage&MessageBody=$util.urlEncode($input.body)

以下示例包括向 SQS 队列发送消息所需的权限:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Resource": [
        "arn:aws:sqs:example-region:example-account-id:example-sqs-queue-name"
      ],
      "Action": [
        "sqs:SendMessage"
      ]
    }
  ]
}

**注意:**将 example-region 替换为您的区域,将 example-account-id 替换为您的账户 ID,将 example-sqs-queue-name 替换为您的 SQS 队列名称。

KMS.AccessDeniedException 错误

AWS 查询协议和 AWS JSON 协议都可能出现 KMS.AccessDeniedException 错误。

当 API 集成执行角色无法通过 AWS Key Management Service(AWS KMS)执行操作时,就会出现 KMS.AccessDeniedException 错误。要解决此错误,必须配置权限,才能对附加到 Amazon SQS 服务器端加密队列的 AWS KMS 密钥执行操作。

以下示例包括对附加到 SQS 队列的 KMS 密钥执行操作所需的权限:

{
  "Sid": "Allow use of the key",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::example-account-id:role/example-api-gw-integration-execution-role"
  },
  "Action": [
    "kms:Encrypt",
    "kms:GenerateDataKey*",
    "kms:Decrypt"
  ],
  "Resource": "*"
}

**注意:**将 example-account-id 替换为您的账户 ID,将 example-api-gw-integration-execution-role 替换为您的执行角色名称。

SignatureDoesNotMatch 错误

使用 AWS 查询协议时,可能会出现 SignatureDoesNotMatch 错误。

集成请求HTTP 方法设置为 GET 而不是 POST 时,会出现 SignatureDoesNotMatch 错误。要解决此错误,请将 HTTP 方法设置为 POST。

InvalidAddress 错误

使用 AWS JSON 协议时,可能会出现 InvalidAddress 错误。

当正文有效载荷中的 SQS 队列 URL 不正确时,就会出现 InvalidAddress 错误。要解决此错误,请检查 API 调用所针对的 SQS 队列的队列 URL。

SerializationException 错误

使用 AWS JSON 协议时,可能会出现 SerializationException 错误。

当正文有效载荷为无效的 JSON 时,会出现 SerializationException 错误。例如,您的 JSON 可能缺少一个逗号或存在多余的逗号,或者缺少大括号或存在多余的大括号。要解决此错误,请使用 JSON 格式化工具查找 JSON 中的语法错误。

MissingRequiredParameterException 错误

使用 AWS JSON 协议时,可能会出现 MissingRequiredParameterException 错误。

当您没有在正文有效载荷中包含一个或多个必要参数时,就会出现 MissingRequiredParameterException 错误。所需的参数取决于您的 API 调用。例如,当缺少 MessageBody 参数时,就会从 SendMessage API 调用中得到这个错误。有关所需的参数和语法,请查看 SQS API 参考

相关信息

将 Amazon API Gateway 与 Amazon SQS 集成以处理异步 REST API

如何使用 API Gateway 作为其他 AWS 服务的代理?