Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract websocket connection Id and other details from websocket in AWS Api Gateway with HTTP integration

I have an http endpoint https://websocketsample.free.beeceptor.com and an API Gateway in AWS for Websockets with routes for $connect, $disconnect and $default, all of them integrated with HTTP integration to a POST https://websocketsample.free.beeceptor.com so that I can capture the http request.

When I test it with wscat

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

I can see the HTTP requests received at the HTTP server (in my case beeceptor). The problem is that $connect and $disconnect don't have any payload in the POST request, only http headers. Example:

  • When I $connect to websocket I get
    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"
    }
    
  • When I send any message to the websocket such as {"action":"action1"} I get
    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"
    }
    
  • And when I $disconnect the websocket I get
    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"
    }
    

How can I get the connection Id so that I can track every websocket session independently? When I tested this with lambda, the request had a requestContext where I could extract the connectionId and use DynamoDb to manage connections. I don't want to use AWS Lambda, I have already an http back-end service which can deal with this. But HTTP integration does not seem to provide much information.


Update 1: This article may explain some of the reasons https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-data-mapping.html Apparently:

"Data mapping for WebSocket APIs isn't supported in the AWS Management Console. You must use the AWS CLI, AWS CloudFormation, or an SDK to configure data mapping."

So it may be that I need to configure data mapping outside the console and hopefully build up a payload that makes sense


Update 2: I've added request parameters as per https://docs.aws.amazon.com/apigateway/latest/developerguide/websocket-api-data-mapping.html#websocket-mapping-request-parameters but no luck

$ 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
}

A connection request still doesn't get forwarded to beeceptor with connectionId in http headers or anywhere and I don't know how to achieve that.

Plus.. I found what it seems an issue in API Gateway API Websocket when creating http endpoints: Unable to use different HTTP verbs in API Gateway with API Websocket and HTTP integration

Not the most intuitive documentation or usage.


SOLUTION: As per the marked answer, the solution was as easy as re-deploying the API. The request parameters would be then forwarded properly.

"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
        }
    ]
like image 544
diegosasw Avatar asked Sep 20 '25 04:09

diegosasw


1 Answers

You have most likely forgotten to deploy your API (Routes -> Actions -> Deploy API). WebSocket APIs still use the old console which does not have auto deploy.

It works when I try it

        {
            "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
        },

Headers:

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]
like image 64
sepbot Avatar answered Sep 22 '25 06:09

sepbot