npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

aws-apigw-ws-emulator

v0.0.4

Published

Local emulator for AWS API Gateway WebSocket with HTTP integration support

Readme

AWS WebSocket Gateway Local

A lightweight local emulator for AWS API Gateway WebSocket with HTTP integration support.

npm version License: MIT

Why?

AWS API Gateway WebSocket supports HTTP integration, allowing you to route WebSocket events to your HTTP backend. However, there's no good open-source solution for local development:

  • LocalStack: WebSocket support requires Pro (paid) version
  • serverless-offline: Only supports Lambda integration, not HTTP

This tool fills that gap - a simple, standalone emulator that:

  • Accepts WebSocket connections from your frontend
  • Forwards $connect, $disconnect, $default events to your HTTP backend
  • Provides /@connections/{connectionId} endpoint for postToConnection

Quick Start

Using npx (no installation)

npx aws-apigw-ws-emulator --backend http://localhost:8080

Using npm

npm install -g aws-apigw-ws-emulator
aws-apigw-ws-emulator --backend http://localhost:8080

Using Docker

docker run -p 3001:3001 ghcr.io/m1heng/aws-apigw-ws-emulator

Architecture

┌──────────────┐     WebSocket      ┌─────────────────────┐     HTTP POST      ┌──────────────────┐
│   Frontend   │◄──────────────────►│  aws-ws-gateway-    │───────────────────►│   Your Backend   │
│              │  ws://localhost    │  local (:3001)      │                    │   (:8080)        │
│              │  :3001?token=...   │                     │  /api/.../connect  │                  │
└──────────────┘                    └──────────┬──────────┘  /api/.../default  └────────┬─────────┘
       ▲                                       │             /api/.../disconnect        │
       │                                       │                                        │
       │                                       │◄───────────────────────────────────────┘
       │                                       │  POST /@connections/{connectionId}
       └───────────────────────────────────────┘  (postToConnection)

Usage

CLI Options

aws-apigw-ws-emulator [options]

Options:
  -p, --port <port>              WebSocket server port (default: 3001)
  -s, --stage <stage>            API stage name (default: local)
  --idle-timeout <seconds>       Idle timeout in seconds (default: 600)
  --hard-timeout <seconds>       Hard timeout in seconds (default: 7200)
  -c, --config <file>            Config file (YAML or JSON)
  -v, --verbose                  Enable verbose logging
  -h, --help                     Display help

Config File

Create gateway.config.yaml:

port: 3001
stage: local

routes:
  $connect:
    uri: http://localhost:8080/ws/connect
  $disconnect:
    uri: http://localhost:8080/ws/disconnect
  $default:
    uri: http://localhost:8080/ws/default

idleTimeout: 600
hardTimeout: 7200
verbose: false

Run with config:

aws-apigw-ws-emulator -c gateway.config.yaml

Integration Guide

Backend Requirements

Your backend receives AWS Lambda-style WebSocket events via HTTP POST:

interface AWSWebSocketEvent {
  requestContext: {
    routeKey: '$connect' | '$disconnect' | '$default' | string;
    eventType: 'CONNECT' | 'DISCONNECT' | 'MESSAGE';
    connectionId: string;
    connectedAt: number;
    domainName: string;
    stage: string;
    apiId: string;
    requestId: string;
    identity: { sourceIp: string; userAgent?: string };
    // MESSAGE only
    messageId?: string;
    // DISCONNECT only
    disconnectStatusCode?: number;
    disconnectReason?: string;
  };
  headers?: Record<string, string>;
  queryStringParameters?: Record<string, string> | null;
  body: string | null;
  isBase64Encoded: boolean;
}

Example request to your $connect endpoint:

{
  "requestContext": {
    "routeKey": "$connect",
    "eventType": "CONNECT",
    "connectionId": "abc123xyz456=",
    "connectedAt": 1704067200000,
    "domainName": "localhost:3001",
    "stage": "local",
    "apiId": "local",
    "requestId": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx",
    "identity": { "sourceIp": "127.0.0.1", "userAgent": "..." }
  },
  "headers": { "origin": "http://localhost:3000", ... },
  "queryStringParameters": { "token": "xxx", "conversationId": "123" },
  "body": null,
  "isBase64Encoded": false
}

Sending Messages to Clients (postToConnection)

Use the Management API to send messages back to clients:

# Using curl
curl -X POST http://localhost:3001/@connections/{connectionId} \
  -H "Content-Type: application/json" \
  -d '{"type": "message", "data": "Hello!"}'
// Using AWS SDK (Java)
ApiGatewayManagementApiClient client = ApiGatewayManagementApiClient.builder()
    .endpointOverride(URI.create("http://localhost:3001"))
    .region(Region.US_WEST_1)
    .credentialsProvider(StaticCredentialsProvider.create(
        AwsBasicCredentials.create("test", "test")))
    .build();

client.postToConnection(PostToConnectionRequest.builder()
    .connectionId(connectionId)
    .data(SdkBytes.fromUtf8String("{\"message\": \"Hello!\"}"))
    .build());
// Using AWS SDK (JavaScript)
const client = new ApiGatewayManagementApiClient({
  endpoint: 'http://localhost:3001',
  region: 'us-west-1',
  credentials: { accessKeyId: 'test', secretAccessKey: 'test' },
});

await client.send(new PostToConnectionCommand({
  ConnectionId: connectionId,
  Data: Buffer.from(JSON.stringify({ message: 'Hello!' })),
}));

Frontend Connection

// Same code works for both local and production!
const wsUrl = process.env.NEXT_PUBLIC_WS_URL; // ws://localhost:3001 or wss://xxx.amazonaws.com

const ws = new WebSocket(`${wsUrl}?token=${token}&conversationId=${conversationId}`);

ws.onmessage = (event) => {
  console.log('Received:', event.data);
};

Environment Configuration

Use the same codebase for local and production:

# application.yml (Spring Boot)
aws:
  apigateway:
    callback: ${AWS_APIGATEWAY_CALLBACK:https://xxx.execute-api.us-west-1.amazonaws.com/prod}
# Local development
AWS_APIGATEWAY_CALLBACK=http://localhost:3001 ./mvnw spring-boot:run

# Production
AWS_APIGATEWAY_CALLBACK=https://xxx.execute-api.us-west-1.amazonaws.com/prod java -jar app.jar

API Reference

Management API

| Method | Path | Description | |--------|------|-------------| | POST | /@connections/{connectionId} | Send message to connection (postToConnection) | | GET | /@connections/{connectionId} | Get connection info | | DELETE | /@connections/{connectionId} | Close connection | | GET | /health | Health check |

Health Check Response

{
  "status": "ok",
  "connections": 5,
  "uptime": 3600.123
}

Comparison with Alternatives

| Feature | aws-apigw-ws-emulator | LocalStack | serverless-offline | |---------|---------------------|------------|-------------------| | HTTP Integration | ✅ | ✅ (Pro only) | ❌ | | Lambda Integration | ❌ | ✅ | ✅ | | Free | ✅ | ❌ ($35/mo) | ✅ | | Standalone | ✅ | ✅ | ❌ (needs SF) | | postToConnection | ✅ | ✅ | ✅ | | Easy Setup | ✅ One command | ⚠️ Complex | ⚠️ Complex |

Programmatic Usage

import { AWSWebSocketGateway } from 'aws-apigw-ws-emulator';

const gateway = new AWSWebSocketGateway({
  port: 3001,
  routes: {
    $connect: { uri: 'http://localhost:8080/ws/connect' },
    $disconnect: { uri: 'http://localhost:8080/ws/disconnect' },
    $default: { uri: 'http://localhost:8080/ws/default' },
  },
  verbose: true,
});

await gateway.start();

// Get connection count
console.log(`Active connections: ${gateway.getConnectionCount()}`);

// Graceful shutdown
await gateway.stop();

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE for details.