【问题标题】:apigateway websocket sqs integrationapigateway websocket sqs 集成
【发布时间】:2021-11-30 22:14:17
【问题描述】:

我正在尝试将 API Gateway WebSocket 路由与 SQS 集成。

我已经使用以下属性配置了 SQS 集成

AWS 区域:ap-southeast-1 AWS 服务:SQS HTTP 方法:POST 路径覆盖:111111110111/my-queue

将请求模板配置为

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

set($context.requestOverride.header.Content-Type="application/x-www-form-urlencoded")##"

当我尝试将数据发送到 SQS 时失败并出现以下错误

错误:

(VK1mEHZSyQ0FlZg=) 转换后的端点请求正文:Action=SendMessage&MessageBody=foobar (VK1mEHZSyQ0FlZg=) 发送请求到https://sqs.ap-southeast-1.amazonaws.com/111111110111/my-queue (VK1mEHZSyQ0FlZg=) 收到响应。集成延迟:16 毫秒 (VK1mEHZSyQ0FlZg=) 转换前的端点响应正文:无法确定要授权的服务/操作名称

【问题讨论】:

  • 我相信您想将路径设置为/,并将QueueUrl 放入body mapping 模板中,就像我在stackoverflow.com/a/49566676/1695906 中所做的那样。
  • 试过没用。使用 REST API,它按预期工作,问题似乎出在“WebSocket”
  • 目前不支持带有 SQS/SNS 的 WebSocket API(不确定是否支持其他 AWS 服务)。得到了 AWS Support 团队的确认。目前,无法将 HTTP 标头映射/添加为 WebSocket API 集成请求的一部分。

标签: amazon-web-services websocket aws-api-gateway amazon-sqs


【解决方案1】:

晚了将近一年,但我想出了一个方法来做到这一点。您无法从控制台本身执行此操作,但您可以通过 CLI 使其工作。

this guide 中涵盖了大部分步骤,但将其设为 WS api 而不是 REST api。

您会注意到无法指定 HTTP 标头,也无法指定映射模板。出于某种原因,这在控制台上不可用。您必须改为通过 CLI 执行此操作。将以下内容另存为 JSON 文件。

{
  "PassthroughBehavior": "NEVER",
  "RequestParameters": {
    "integration.request.header.Content-Type": "'application/x-www-form-urlencoded'"
  },
  "RequestTemplates": {
    "application/json": "Action=SendMessage&MessageBody=$util.urlEncode($input.body)"
  }
}

并像这样更新集成:

aws apigatewayv2 update-integration \ 
--api-id API_ID \
--integration-id INTEGRATION_ID \
--cli-input-json file://update.json

您将在 API 概览的控制台上看到 API ID,但您必须通过 CLI 找到集成 ID,如下所示:

aws apigatewayv2 get-integrations --api-id API_ID

这会导致正文本身以明文形式发送到 SQS 队列。

注意:如果您使用 CloudFormation/SAM 创建 API,则可以放弃所有这些,因为这样您就可以直接设置 RequestParameters 和 RequestTemplates。

【讨论】:

    【解决方案2】:

    提升@Aksel's answer 答案:这是一个 Terraform 解决方案;以防有人在搜索它。

    Terraform's documentation 给出的示例不适用于我。


    以下tf文件基于@Aksel's answer

    main.tf

    • 定义 AWS 区域并获取调用者身份
    # main.tf
    
    # AWS region
    variable "aws_region" {
      description = "AWS region"
      type        = string
      default     = "ap-southeast-1"
      # default     = "ap-northeast-1"
      # default     = "us-east-1"
    }
    
    # Caller identity
    data "aws_caller_identity" "current" {}
    

    iam.tf

    • 为 API Gateway 设置角色,附加角色策略以允许向 SQS 发送消息
    # iam.tf
    
    resource "aws_iam_role" "apigw_sqs_role" {
      name               = "api_sqs_role"
      assume_role_policy = <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Principal": {
            "Service": "apigateway.amazonaws.com"
          },
          "Effect": "Allow",
          "Sid": ""
        }
      ]
    }
    EOF
    }
    
    resource "aws_iam_role_policy" "allow_apigw_sqs_policy" {
      name   = "allow_apigw_sqs_policy"
      role   = aws_iam_role.apigw_sqs_role.id
      policy = <<EOF
    {
      "Version":"2012-10-17",
      "Statement":[{
        "Effect":"Allow",
        "Action":[
            "sqs:SendMessage",
        ],
        "Resource":"*"
      }]
    }
    EOF
    }
    
    

    sqs.tf

    • 定义 SQS
    # sqs.tf
    
    resource "aws_sqs_queue" "my_sqs_queue" {
      name = "my-queue"
    }
    
    

    apigateway.tf

    • 使用 websocket 协议定义 API 网关
    • 设置 $default 路由并附加集成
    • apigateway 集成:
      • integration_type = "AWS" 和 integration_method = "POST"
      • integration_uri = arn:aws:apigateway:&lt;aws_region&gt;:sqs:path/&lt;aws_account_id&gt;/&lt;sqs_name&gt;
        • 例如arn:aws:apigateway:ap-southeast-1:sqs:path/111111110111/my-queue
      • credentials_arn 是iam.tf 中定义的角色
    # apigateway.tf
    
    # API Gateway
    resource "aws_apigatewayv2_api" "apigw_websocket" {
      name                       = "websocket-api"
      protocol_type              = "WEBSOCKET"
      route_selection_expression = "$request.body.action"
    }
    
    resource "aws_apigatewayv2_route" "apigw_websocket_default_route" {
      api_id                              = aws_apigatewayv2_api.apigw_websocket.id
      route_key                           = "$default"
      route_response_selection_expression = "$default"
      target                              = "integrations/${aws_apigatewayv2_integration.apigw_websocket_default_integration_sqs.id}"
    }
    
    resource "aws_apigatewayv2_integration" "apigw_websocket_default_integration_sqs" {
      api_id               = aws_apigatewayv2_api.apigw_websocket.id
      integration_type     = "AWS"
      integration_method   = "POST"
      integration_uri      = "arn:aws:apigateway:${var.aws_region}:sqs:path/${data.aws_caller_identity.current.account_id}/${aws_sqs_queue.my_sqs_queue.name}/"
      credentials_arn      = aws_iam_role.apigw_sqs_role.arn
      passthrough_behavior = "NEVER"
      request_parameters = {
        "integration.request.header.Content-Type" = "'application/x-www-form-urlencoded'"
      }
      request_templates = {
        "application/json" : "Action=SendMessage&MessageBody=$util.urlEncode($input.body)"
      }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2021-11-23
      • 1970-01-01
      • 2020-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 2020-02-15
      相关资源
      最近更新 更多