Amazon web services 如何使用RequestTemplates通过HTTP集成修改API网关中的WebSocket请求

Amazon web services 如何使用RequestTemplates通过HTTP集成修改API网关中的WebSocket请求,amazon-web-services,websocket,amazon-cloudformation,aws-api-gateway,Amazon Web Services,Websocket,Amazon Cloudformation,Aws Api Gateway,我有一个http端点(例如https://sample-sasw.free.beeceptor.com) 以及API网关的websocket API与http集成,如AWS CloudFormation模板中所示 我希望能够连接到websocket: wscat -c wss://nghixzq757.execute-api.eu-west-1.amazonaws.com/production 将$connect发送到我的HTTP端点。 如果可能的话,我想在https://sample-sas

我有一个http端点(例如
https://sample-sasw.free.beeceptor.com
) 以及API网关的websocket API与http集成,如AWS CloudFormation模板中所示

我希望能够连接到websocket:

wscat -c wss://nghixzq757.execute-api.eu-west-1.amazonaws.com/production
$connect
发送到我的HTTP端点。 如果可能的话,我想在
https://sample-sasw.free.beeceptor.com/connect
在API网关上生成特定的JSON负载,例如

{
  "connectionId": "foEf1d_ejoECHeQ=",
  "domainName": "nghixzq757.execute-api.eu-west-1.amazonaws.com",
  "stage": "production"
}
即使原始
$connect
中没有正文。如果这不可能,那也没关系,因为我已经将这些参数作为http头获取了。

一旦连接到websocket,我希望能够通过websocket发送任何有效负载,该负载将在
https://sample-sasw.free.beeceptor.com/sendMessage
,但将JSON负载转换为仅获取
数据
属性。换句话说,我想要这样的东西:

wscat -c wss://nghixzq757.execute-api.eu-west-1.amazonaws.com/production

Connected (press CTRL+C to quit)

> {'action': 'sendMessage', 'data': '{'foo': 'bar'}'}
< OK!!
我不能让它工作。我花了好几个小时试图找到关于如何使用CloudFormation YML的
RequestTemplates
TemplateSelectionExpression
的好例子,以理解它或让一个简单的例子起作用

我得到了一些结果

$ wscat -c wss://nghixzq757.execute-api.eu-west-1.amazonaws.com/production
Connected (press CTRL+C to quit)
> {'action': 'sendMessage', 'data': {'foo': 'bar'}}
< {"message": "Internal server error", "connectionId":"foEf1d_ejoECHeQ=", "requestId":"foFlwEtkjoEFkWw="}
> {'action': 'sendMessage', 'data': ''}
< {"message": "Internal server error", "connectionId":"foEf1d_ejoECHeQ=", "requestId":"foFlwEtkjoEFkWw="}
$ wscat -c wss://nghixzq757.execute-api.eu-west-1.amazonaws.com/production
Connected (press CTRL+C to quit)
> {'action': 'sendMessage', 'data': {'foo': 'bar'}}
< {"message": "Internal server error", "connectionId":"foEf1d_ejoECHeQ=", "requestId":"foFlwEtkjoEFkWw="}
> {'action': 'sendMessage', 'data': ''}
< {"message": "Internal server error", "connectionId":"foEf1d_ejoECHeQ=", "requestId":"foFlwEtkjoEFkWw="}
AWSTemplateFormatVersion: 2010-09-09

Description: Sample API Gateway with Websocket

Parameters:
  hostname:
    Type: String
    Description: The hostname to use in http integration
    Default: sample-sasw.free.beeceptor.com

Resources:
  websocketApiGateway:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: sample-websocket-gateway
      Description: Api Gateway for websocket
      ProtocolType: WEBSOCKET
      RouteSelectionExpression: $request.body.action

  connectRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteKey: $connect
      AuthorizationType: NONE
      OperationName: ConnectRoute
      RouteResponseSelectionExpression: $default
      Target: !Join
        - /
        - - integrations
          - !Ref connectIntegration

  connectIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref websocketApiGateway
      Description: Websocket $connect integration
      ConnectionType: INTERNET
      IntegrationType: HTTP_PROXY # no need to transform payload in $connect
      IntegrationMethod: POST
      IntegrationUri: !Sub https://${hostname}/connect
      RequestParameters:
        "integration.request.header.domainName": "context.domainName"
        "integration.request.header.stage": "context.stage"
        "integration.request.header.connectionId": "context.connectionId"
      PayloadFormatVersion: 1.0

  connectRouteResponse:
    Type: AWS::ApiGatewayV2::RouteResponse
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteId: !Ref connectRoute
      RouteResponseKey: $default

  sendMessageRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteKey: sendMessage
      AuthorizationType: NONE
      OperationName: SendMessageRoute
      RouteResponseSelectionExpression: $default
      Target: !Join
        - /
        - - integrations
          - !Ref sendMessageIntegration

  sendMessageIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref websocketApiGateway
      Description: Websocket sendMessage integration
      IntegrationType: HTTP
      IntegrationMethod: POST
      IntegrationUri: !Sub https://${hostname}/sendmessage
      RequestParameters:
        "integration.request.header.domainName": "context.domainName"
        "integration.request.header.stage": "context.stage"
        "integration.request.header.connectionId": "context.connectionId"
      RequestTemplates: # HOW DOES THIS WORK??
        "connectionId": "$context.connectionId"
        # "body": "$input.body"
      TemplateSelectionExpression: \$default # match all incoming requests
      PayloadFormatVersion: 1.0

  sendRouteResponse:
    Type: AWS::ApiGatewayV2::RouteResponse
    Properties:
      ApiId: !Ref websocketApiGateway
      RouteId: !Ref sendMessageRoute
      RouteResponseKey: $default

  websocketStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      StageName: production
      Description: Production stage
      AutoDeploy: true
      ApiId: !Ref websocketApiGateway
  
Outputs:
  websocketUri:
    Description: Websocket root URL
    Value: !Sub wss://${websocketApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${websocketStage}