Skip to content

Instantly share code, notes, and snippets.

@serverlessunicorn
Last active April 18, 2020 13:44
Show Gist options
  • Save serverlessunicorn/7b84af5d540b1ec6c1e0102b64becd3b to your computer and use it in GitHub Desktop.
Save serverlessunicorn/7b84af5d540b1ec6c1e0102b64becd3b to your computer and use it in GitHub Desktop.

Revisions

  1. serverlessunicorn revised this gist Sep 30, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion MediumCFArticle8.yaml
    Original file line number Diff line number Diff line change
    @@ -156,7 +156,7 @@
    NATPunchPairModel:
    Type: AWS::ApiGatewayV2::Model
    Properties:
    Name: NATPunchWebSocketPairModel # Must match NATPunchPairRoute.RequstModels value
    Name: NATPunchWebSocketPairModel # Must match NATPunchPairRoute.RequestModel value
    ApiId: !Ref NATPunchWebSocket
    ContentType: application/json
    Schema:
  2. serverlessunicorn created this gist Sep 30, 2019.
    228 changes: 228 additions & 0 deletions MediumCFArticle8.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,228 @@
    # The top-level websocket itself
    NATPunchWebSocket:
    Type: AWS::ApiGatewayV2::Api
    Properties:
    Name: NATPunchWebSocket
    ProtocolType: WEBSOCKET
    RouteSelectionExpression: "$request.body.action"

    # The builtin $connect path. This involves both a route
    # definition and its integration definition, which follows, as well as a
    # synchronous response from the Lambda proxy that returns success/failure info to the caller.
    NATPunchConnectRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
    ApiId: !Ref NATPunchWebSocket
    RouteKey: $connect
    AuthorizationType: NONE
    OperationName: NATPunchConnectRoute
    # A Lambda proxy response is used for $connect messages to return
    # success/failure info to the caller.
    # See the matching response section following the integration definition.
    RouteResponseSelectionExpression: $default
    Target: !Join ['/', [integrations, !Ref NATPunchConnectInteg]] # See below

    # The Lambda proxy for $connect.
    NATPunchConnectInteg:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
    ApiId: !Ref NATPunchWebSocket
    Description: Integration for builtin $connect route
    IntegrationType: AWS_PROXY
    # All routes lead to the same Lambda function; it uses the route
    # provided by API Gateway to determine the right behavior.
    IntegrationUri:
    !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${NATPunchFunction.Arn}/invocations

    # The Lambda proxy response to $connect, which returns success/failure info to the caller.
    NATPunchConnectRouteResponse:
    Type: 'AWS::ApiGatewayV2::RouteResponse'
    Properties:
    RouteId: !Ref NATPunchConnectRoute
    ApiId: !Ref NATPunchWebSocket
    RouteResponseKey: $default

    # The builtin $disconnect path. This involves both a route
    # definition and its integration definition, which follows, as well as a
    # synchronous response from the Lambda proxy.
    NATPunchDisconnectRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
    ApiId: !Ref NATPunchWebSocket
    RouteKey: $disconnect
    AuthorizationType: NONE
    OperationName: NATPunchDisconnectRoute
    # A Lambda proxy response is used for $disconnect messages to return
    # success/failure info to the caller.
    # See the matching response section following the integration definition.
    RouteResponseSelectionExpression: $default
    Target: !Join ['/', [integrations, !Ref NATPunchDisconnectInteg]]

    # The Lambda proxy for $disconnect.
    NATPunchDisconnectInteg:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
    ApiId: !Ref NATPunchWebSocket
    Description: Integration for builtin $disconnect route
    IntegrationType: AWS_PROXY
    # All routes lead to the same Lambda function; it uses the route
    # provided by API Gateway to determine the right behavior.
    IntegrationUri:
    !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${NATPunchFunction.Arn}/invocations

    # The Lambda proxy response to $disconnect, which returns success/failure info to the caller.
    NATPunchDisconnectRouteResponse:
    Type: 'AWS::ApiGatewayV2::RouteResponse'
    Properties:
    RouteId: !Ref NATPunchDisconnectRoute
    ApiId: !Ref NATPunchWebSocket
    RouteResponseKey: $default

    # The builtin $default path. This involves both a route
    # definition and its integration definition, which follows, as well as a
    # synchronous response from the Lambda proxy.
    # The NATPunch websocket does *not* rely on the $default route for anything constructive;
    # any calls it are, by definition, errors and return a "malformed request" argument.
    # TODO: Consider adding a dummy model to $default, to force API Gateway to reject these
    # requests and avoid paying for Lambda calls just to respond "malformed message".
    NATPunchDefaultRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
    ApiId: !Ref NATPunchWebSocket
    RouteKey: $default
    AuthorizationType: NONE
    OperationName: NATPunchDefaultRoute
    # A Lambda proxy response is used for $default messages to immediately inform
    # the caller that the request was malformed.
    # See the matching response section following the integration definition.
    RouteResponseSelectionExpression: $default
    Target: !Join ['/', [integrations, !Ref NATPunchDefaultInteg]]

    # Lambda proxy integratino for $default route
    NATPunchDefaultInteg:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
    ApiId: !Ref NATPunchWebSocket
    Description: Integration for builtin $default route
    IntegrationType: AWS_PROXY
    # All routes lead to the same Lambda function; it uses the route
    # provided by API Gateway to determine the right behavior.
    IntegrationUri:
    !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${NATPunchFunction.Arn}/invocations

    # The Lambda proxy response to $default, which returns an error message to the caller that
    # the message it sent was malformed.
    NATPunchDefaultRouteResponse:
    Type: 'AWS::ApiGatewayV2::RouteResponse'
    Properties:
    RouteId: !Ref NATPunchDefaultRoute
    ApiId: !Ref NATPunchWebSocket
    RouteResponseKey: $default

    # Custom 'pair'ing route. This involves both a route
    # definition and its integration definition, which follows.
    # Notes:
    # * This path is async, so there is no response for it. The NATPunch Lambda function will
    # make (asynchronous) HTTPS calls to the response URL for the websocket for each client
    # if & when pairing information is complete.
    # * This path uses model validation. This avoids the need to verify the syntax of the call
    # in the Lambda function by having API Gateway check it.
    NATPunchPairRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
    ApiId: !Ref NATPunchWebSocket
    RouteKey: pair
    AuthorizationType: NONE
    OperationName: NATPunchPairRoute
    # The next three lines can look a little confusing.
    # What they're saying is, "When you see 'pair' as the route, which
    # is value of the 'action' key at the top level of the request's body,
    # then apply 'NATPunchPairModel' to validate it."
    ModelSelectionExpression: "$request.body.action"
    RequestModels:
    pair: NATPunchWebSocketPairModel # This is a name, not a REF
    Target: !Join ['/', [integrations, !Ref NATPunchPairInteg]]

    NATPunchPairInteg:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
    ApiId: !Ref NATPunchWebSocket
    Description: Pairing request integration
    IntegrationType: AWS_PROXY
    IntegrationUri:
    !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${NATPunchFunction.Arn}/invocations

    # The validation model for 'pair' route messages.
    NATPunchPairModel:
    Type: AWS::ApiGatewayV2::Model
    Properties:
    Name: NATPunchWebSocketPairModel # Must match NATPunchPairRoute.RequstModels value
    ApiId: !Ref NATPunchWebSocket
    ContentType: application/json
    Schema:
    $schema: 'http://json-schema.org/draft-04/schema#'
    title: NATPunchPairModelSchema
    type: object
    properties:
    action: {type: string, pattern: "pair"}
    pairing_name: {type: string, pattern: "[_a-z0-9]{1,255}"}
    limit:
    type: number
    required: [action, pairing_name]

    # The custom 'status' path. This involves both a route
    # definition and its integration definition, which follows, as well as a
    # synchronous response from the Lambda proxy.
    NATPunchStatusRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
    ApiId: !Ref NATPunchWebSocket
    RouteKey: status
    AuthorizationType: NONE
    OperationName: NATPunchStatusRoute
    # The next three lines can look a little confusing.
    # What they're saying is, "When you see 'status' as the route, which
    # is value of the 'action' key at the top level of the request's body,
    # then apply 'NATPunchStatusModel' to validate it."
    ModelSelectionExpression: "$request.body.action"
    RequestModels:
    status: NATPunchWebSocketStatusModel # This is a name, not a REF
    # A Lambda proxy response is used for status requests to return
    # connection information to the caller.
    # See the matching response section following the integration definition.
    RouteResponseSelectionExpression: $default
    Target: !Join ['/', [integrations, !Ref NATPunchStatusInteg]]

    NATPunchStatusInteg:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
    ApiId: !Ref NATPunchWebSocket
    Description: Integration for custom 'status' route
    IntegrationType: AWS_PROXY
    # All routes lead to the same Lambda function; it uses the route
    # provided by API Gateway to determine the right behavior.
    IntegrationUri:
    !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${NATPunchFunction.Arn}/invocations

    # The Lambda proxy response to 'status', which returns connection info to the caller.
    StatusRouteResponse:
    Type: 'AWS::ApiGatewayV2::RouteResponse'
    Properties:
    RouteId: !Ref NATPunchStatusRoute
    ApiId: !Ref NATPunchWebSocket
    RouteResponseKey: $default

    # The validation model for 'status' route messages.
    NATPunchStatusModel:
    Type: AWS::ApiGatewayV2::Model
    Properties:
    Name: NATPunchWebSocketStatusModel
    ApiId: !Ref NATPunchWebSocket
    ContentType: application/json
    Schema:
    $schema: 'http://json-schema.org/draft-04/schema#'
    title: NATPunchStatusModelSchema
    type: object
    properties:
    action: {type: string, pattern: "status"}
    required: [action]