通过 HTTP 集成从 AWS Api Gateway 中的 websocket 提取 websocket 连接 ID 和其他详细信息

Posted

技术标签:

【中文标题】通过 HTTP 集成从 AWS Api Gateway 中的 websocket 提取 websocket 连接 ID 和其他详细信息【英文标题】:Extract websocket connection Id and other details from websocket in AWS Api Gateway with HTTP integration 【发布时间】:2021-06-15 17:10:38 【问题描述】:

我有一个 http 端点 https://websocketsample.free.beeceptor.com 以及 AWS 中用于 Websockets 的 API 网关,带有 $connect$disconnect$default 的路由,所有这些都与 HTTP 集成集成到 POST https://websocketsample.free.beeceptor.com,以便我可以捕获 http 请求。

当我用 wscat 测试它时

wscat -c wss://e96ypxXXXX.execute-api.eu-west-3.amazonaws.com/production

我可以看到在 HTTP 服务器(在我的例子中是 beeceptor)收到的 HTTP 请求。问题是 $connect 和 $disconnect 在 POST 请求中没有任何有效负载,只有 http 标头。示例:

当我 $connect 到 websocket 我得到
Request body: empty
Headers:

  "content-length": "0",
  "sec-websocket-extensions": "permessage-deflate; client_max_window_bits",
  "sec-websocket-key": "pTR36OHKUSk8cqBix8vJXA==",
  "sec-websocket-version": "13",
  "x-amzn-trace-id": "Root=1-605322fb-1e2b058363326df80a61df18",
  "x-forwarded-for": "185.153.165.121",
  "x-forwarded-port": "443",
  "x-forwarded-proto": "https",
  "user-agent": "AmazonAPIGateway_e96ypxXXXX",
  "x-amzn-apigateway-api-id": "e96ypxXXXX"

当我向 websocket 发送任何消息时,例如 "action":"action1" 我得到
Request body: "action":"action1"
Headers:

  "content-length": "20",
  "user-agent": "AmazonAPIGateway_e96ypxXXXX",
  "x-amzn-apigateway-api-id": "e96ypxXXXX",
  "content-type": "application/json; charset=UTF-8"

当我 $disconnect websocket 我得到
Request body: empty
Headers:

  "content-length": "0",
  "x-api-key": "",
  "x-forwarded-for": "",
  "x-restapi": "",
  "user-agent": "AmazonAPIGateway_e96ypxXXXX",
  "x-amzn-apigateway-api-id": "e96ypxXXXX"

如何获取连接 ID,以便独立跟踪每个 websocket 会话? 当我使用 lambda 进行测试时,请求有一个 requestContext,我可以在其中提取 connectionId 并使用 DynamoDb 来管理连接。 我不想使用 AWS Lambda,我已经有一个 http 后端服务可以处理这个问题。但 HTTP 集成似乎并没有提供太多信息。


更新1:这篇文章可能会解释一些原因https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-data-mapping.html 显然:

“AWS 管理控制台不支持 WebSocket API 的数据映射。您必须使用 AWS CLI、AWS CloudFormation 或开发工具包来配置数据映射。”

所以我可能需要在控制台之外配置数据映射,并希望构建一个有意义的有效负载


更新 2:我已经按照 https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-data-mapping.html#websocket-mapping-request-parameters 添加了请求参数,但没有运气

$ aws --profile diegosasw apigatewayv2 update-integration --integration-id 3lppdXX --api-id oe9jal8gXX --request-parameters 'integration.request.header.connectionId'='context.connectionId'

    "ConnectionType": "INTERNET",
    "IntegrationId": "3lppdXX",
    "IntegrationMethod": "POST",
    "IntegrationType": "HTTP_PROXY",
    "IntegrationUri": "https://websocketsample.free.beeceptor.com/connections",
    "PassthroughBehavior": "WHEN_NO_MATCH",
    "PayloadFormatVersion": "1.0",
    "RequestParameters": 
        "integration.request.header.connectionId": "context.connectionId"
    ,
    "TimeoutInMillis": 29000

连接请求仍然没有被转发到带有 http 标头或任何地方的 connectionId 的 beeceptor,我不知道如何实现。

另外.. 在创建 http 端点时,我发现 API Gateway API Websocket 中似乎存在问题:Unable to use different HTTP verbs in API Gateway with API Websocket and HTTP integration

不是最直观的文档或用法。


解决方案:根据标记的答案,解决方案就像重新部署 API 一样简单。然后请求参数将被正确转发。

"Items": [
        
            "ConnectionType": "INTERNET",
            "IntegrationId": "okmv0au",
            "IntegrationMethod": "POST",
            "IntegrationType": "HTTP_PROXY",
            "IntegrationUri": "https://awswebsocket.free.beeceptor.com",
            "PassthroughBehavior": "WHEN_NO_MATCH",
            "PayloadFormatVersion": "1.0",
            "RequestParameters": 
                "integration.request.header.domainName": "context.domainName",
                "integration.request.header.stage": "context.stage",
                "integration.request.header.connectionId": "context.connectionId",
                "integration.request.header.messageId": "context.messageId"
            ,
            "TimeoutInMillis": 29000
        
    ]

【问题讨论】:

【参考方案1】:

您很可能忘记部署 API(路由 -> 操作 -> 部署 API)。 WebSocket API 仍然使用没有自动部署的旧控制台。

试一试就可以了

        
            "ConnectionType": "INTERNET",
            "ContentHandlingStrategy": "CONVERT_TO_TEXT",
            "IntegrationId": "iasyqzb",
            "IntegrationMethod": "ANY",
            "IntegrationType": "HTTP_PROXY",
            "IntegrationUri": "[REDACTED]",
            "PassthroughBehavior": "WHEN_NO_MATCH",
            "PayloadFormatVersion": "1.0",
            "RequestParameters": 
                "integration.request.header.connectionId": "context.connectionId"
            ,
            "TimeoutInMillis": 29000
        ,

标题:

connectionid: dL53oem8IAMCK9g=
host: [REDACTED]
sec-websocket-key: dJleaOF55APY+0K6bPJWmg==
sec-websocket-version: 13
user-agent: AmazonAPIGateway_fhyhvnschc
x-amzn-apigateway-api-id: fhyhvnschc
x-amzn-trace-id: Self=1-6067d697-7dc1eea10d51468c3adbbc80;Root=1-6067d697-048e3deb132e05d50553a29e
x-forwarded-for: [REDACTED]

【讨论】:

你说得对。我快到了,但不知道我必须在更新集成后重新部署 API。我现在可以看到 connectionId 和我设置的任何集成请求参数。谢谢

以上是关于通过 HTTP 集成从 AWS Api Gateway 中的 websocket 提取 websocket 连接 ID 和其他详细信息的主要内容,如果未能解决你的问题,请参考以下文章

使用代理集成通过 API Gateway 触发 AWS Lambda

AWS API Gateway 集成响应

使用 HTTP 代理访问 AWS API Gateway 中的标头?

未调用 AWS API Gateway 自定义授权方

如何通过 AWS HTTP API 向 Lambda 发送参数

AWS Lambda 和 API Gateway 响应集成问题