# 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]