首页 > 解决方案 > 连接 AWS API Gateway websocket 时返回连接 ID

问题描述

我正在使用 AWS Cloud Formation 并努力了解 API Gateway 如何用于 Websocket。

我希望$connect路由响应 OK 和 AWS API Gateway 分配的连接 ID。所以例如在做的时候

wscat -c wss://my-custom-api-gateway-ws.com

我希望得到

Connected (press CTRL+C to quit)

和一条消息,例如

< {"message": "Connected". "connectionId": "foo"}

或类似的。但我一直得到一个

wscat -c wss://my-custom-api-gateway-ws.com
error: Unexpected server response: 500

这是我尝试过的

  wsApiGateway:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: !Sub ${prefix}-ws-gateway
      Description: Api Gateway for Websockets
      ProtocolType: WEBSOCKET
      RouteSelectionExpression: $request.body.action
      DisableExecuteApiEndpoint: true

  wsConnectRoute:
    Type: AWS::ApiGatewayV2::Route
    DependsOn:
      - wsConnectIntegration
    Properties:
      ApiId: !Ref wsApiGateway
      RouteKey: $connect
      AuthorizationType: NONE
      OperationName: ConnectRoute
      RouteResponseSelectionExpression: $default
      Target: !Join
        - /
        - - integrations
          - !Ref wsConnectIntegration

  wsConnectIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref wsApiGateway
      Description: Websocket $connect integration
      IntegrationType: MOCK
      RequestTemplates:
        application/json: "{\"statusCode\": 200, \"connectionId\": \"$context.connectionId\", \"message\": \"Success\"}"
      PayloadFormatVersion: 1.0

  wsApiStage:
    Type: AWS::ApiGatewayV2::Stage
    DependsOn:
      - wsConnectRoute
    Properties:
      StageName: production
      Description: Autodeploy in production
      AutoDeploy: true
      ApiId: !Ref wsApiGateway
      AccessLogSettings:
        DestinationArn: !GetAtt wsApiGatewayLogGroup.Arn
        Format: '{"requestTime":"$context.requestTime","requestId":"$context.requestId","connectionId":"$context.connectionId","domainName":"$context.domainName","stage":"$context.stage","httpMethod":"$context.httpMethod","path":"$context.path","routeKey":"$context.routeKey","status":$context.status,"responseLatency":$context.responseLatency, "responseLength":$context.responseLength, "integrationError":$context.integration.error}'

如果我完全删除路由 $connect,我可以连接但它不返回任何消息

wscat -c wss://my-custom-api-gateway-ws.com
Connected (press CTRL+C to quit)

如果我通过 websocket 发送任何内容,我会收到一个包含连接 ID 的自动响应错误(我可以将其用作解决方法)。但是我想在连接时获取该连接 ID,而不是在强制出错时。

wscat -c wss://my-custom-api-gateway-ws.com
Connected (press CTRL+C to quit)
> this is a silly message
< {"message": "Forbidden", "connectionId":"H-SaJeT8oECIUg=", "requestId":"H-SbUEHSoEF3JQ="}

我的理解是我应该能够让它与 MOCK 集成类型一起使用,因为我不需要集成 http 服务或类似服务,并且 API 网关应该具有响应所需的所有内容。

有没有人取得类似的成就?


更新 1 我已经手动(还没有云形成)按照在 AWS ApiGateway中设置基本 WebSocket 模拟的步骤添加一个 $connect 路由,与 MOCK 集成,一个响应模板

{"statusCode" : 200, "connectionId" : "$context.connectionId"}

但连接时我看不到那个connectionId。

wscat -c wss://foo.execute-api.eu-west-1.amazonaws.com/production
Connected (press CTRL+C to quit)

另外,如果我添加了一个 $default 路由,那么一旦连接,我就可以向 websocket 发送消息并接收预期的 connectionId,但我似乎没有找到一种方法来仅通过$connect没有任何其他路由的路由接收 connectionId。

标签: websocketamazon-cloudformationaws-api-gateway

解决方案


您正在尝试将 HTTP 响应返回到 websocket;一旦转换为 websocket,您将无法再使用 HTTP 响应。

我只是返回一个null. 要将数据发送到客户端,请启动 Lambda 并使用postToConnectionAPI 函数通过 connectionId 推送数据。(这里是Javascript SDK的链接。)


编辑:

唔。我在较新的代码中看到我确实{ statusCode: 200 }从我的 Lambda 中返回返回值,但仅此而已。内容仍然通过 API 调用发出。


推荐阅读