Skip to main content

WebSocket

WebSocket is currently supported through the following generators (channels):

LanguagesClient PublishClient SubscribeServer Register
TypeScript✅✅✅

All of this is available through AsyncAPI.

⚠️ Important: External Connection Management​

The WebSocket generator assumes that WebSocket connections are managed externally by your application. The generated functions accept already-connected WebSocket instances and focus on message handling rather than connection establishment.

// ✅ You manage the connection
const clientWs = new WebSocket('ws://localhost:8080/user/events');
const server = new WebSocketServer({ port: 8080 });

// ✅ Generated functions use your connections
await publishMessage({ message, parameters, ws: clientWs });
registerHandler({ wss: server, onConnection, onMessage });

Why External Connection Management:

  • Gives you full control over connection lifecycle
  • Allows custom authentication and authorization
  • Enables connection pooling and reconnection strategies
  • Separates transport concerns from message handling

Channels​

Read more about the channels generator here before continuing.

This generator provides support functions for each resource ensuring you use the right payload and parameters.

Input (AsyncAPI)Using the code
asyncapi: 3.0.0
info:
title: User Service
version: 1.0.0
description: WebSocket-based user event system
channels:
userEvents:
address: user/events/{userId}
parameters:
userId:
description: The user identifier
messages:
userSignedUp:
$ref: '#/components/messages/UserSignedUp'
operations:
sendUserEvent:
action: send
channel:
$ref: '#/channels/userEvents'
receiveUserEvent:
action: receive
channel:
$ref: '#/channels/userEvents'
components:
messages:
UserSignedUp:
payload:
type: object
properties:
userId:
type: string
email:
type: string
required:
- userId
- email

Client-side publishing:

import { publishToSendUserEvent } from './channels';
import { UserSignedUp } from './payloads';
import { UserEventsParameters } from './parameters';
import WebSocket from 'ws';

// Create connection (your responsibility)
const ws = new WebSocket('ws://localhost:8080/user/events/user123');

await ws.on('open', async () => {
// Use generated publish function
// Channel parameters are part of the connection URL, so the publish
// function only takes the message and the socket.
await publishToSendUserEvent({
message: new UserSignedUp({
userId: 'user123',
email: 'user@example.com'
}),
ws
});
});

Client-side subscribing:

import { subscribeToReceiveUserEvent } from './channels';

ws.on('open', () => {
// Set up subscription
subscribeToReceiveUserEvent({
onDataCallback: (params) => {
const { err, msg, parameters, ws } = params;
if (err) {
console.error('Error:', err);
return;
}

console.log('Received:', msg?.marshal());
console.log('User ID:', parameters?.userId);
},
parameters: new UserEventsParameters({
userId: 'user123'
}),
ws
});
});

Server-side handling:

import { registerSendUserEvent } from './channels';
import WebSocket from 'ws';

// Create server (your responsibility)
const wss = new WebSocket.WebSocketServer({ port: 8080 });

// Register message handler
registerSendUserEvent({
wss,
onConnection: (params) => {
const { parameters, ws, request } = params;
console.log(`User ${parameters.userId} connected`);

// Perform authentication, logging, etc.
},
onMessage: (params) => {
const { message, ws } = params;
console.log('Received message:', message.marshal());

// Process the message
// Send response if needed
const response = new UserSignedUp({
userId: message.userId,
email: 'updated@example.com'
});
ws.send(response.marshal());
}
});

Function Types​

The WebSocket generator creates three types of functions:

Client Functions​

Publish Functions (publishTo*):

  • Send messages from client to server
  • Require connected WebSocket instance
  • Handle message serialization automatically
  • Return Promise for async operation

Subscribe Functions (subscribeTo*):

  • Listen for messages from server
  • Set up message handlers on WebSocket
  • Handle message parsing and validation
  • Support error handling through callbacks

Server Functions​

Register Functions (register*):

  • Handle incoming client connections
  • Process messages from clients
  • Support both connection and message callbacks
  • Enable URL parameter extraction

URL Pattern Matching​

The WebSocket generator automatically creates URL pattern matching for channels with parameters:

# AsyncAPI Channel
channels:
userEvents:
address: user/events/{userId}/{eventType}
// Generated pattern matching
// Matches: /user/events/123/signup
// Extracts: userId="123", eventType="signup"

registerSendUserEvent({
wss,
onConnection: (params) => {
// Parameters automatically extracted from URL
const { parameters } = params;
console.log(parameters.userId); // "123"
console.log(parameters.eventType); // "signup"
},
onMessage: (params) => {
// Handle the message
}
});

Error Handling​

The WebSocket generator includes comprehensive error handling:

// Client-side error handling
subscribeToReceiveUserEvent({
onDataCallback: (params) => {
const { err, msg } = params;
if (err) {
// Handle parsing errors, validation errors, etc.
console.error('Message error:', err.message);
return;
}
// Process successful message
},
ws
});

// Connection state checking
await publishToSendUserEvent({
message,
parameters,
ws // Function checks if WebSocket is open
});

Best Practices​

Connection Management​

// ✅ Handle connection lifecycle
const ws = new WebSocket('ws://localhost:8080/user/events/123');

ws.on('open', () => {
// Set up subscriptions after connection opens
subscribeToReceiveUserEvent({ ... });
});

ws.on('close', (code, reason) => {
// Handle disconnection, implement reconnection logic
});

ws.on('error', (error) => {
// Handle connection errors
});

Message Validation​

// ✅ Use validation in production
subscribeToReceiveUserEvent({
onDataCallback: (params) => {
const { err, msg } = params;
if (err) {
// Generated functions include validation errors
console.error('Invalid message received:', err);
return;
}
// Message is guaranteed to be valid
},
skipMessageValidation: false, // Enable validation (default)
ws
});

Server Setup​

// ✅ Proper server setup with error handling
const wss = new WebSocket.WebSocketServer({
port: 8080,
verifyClient: (info) => {
// Implement authentication logic
return true;
}
});

registerSendUserEvent({
wss,
onConnection: (params) => {
const { parameters, ws, request } = params;

// Validate parameters
if (!parameters.userId) {
ws.close(1008, 'Invalid user ID');
return;
}

// Set up user session
},
onMessage: (params) => {
const { message, ws } = params;

try {
// Process message safely
} catch (error) {
ws.close(1011, 'Processing error');
}
}
});

Dependencies​

The generated WebSocket code requires the ws library:

npm install ws
npm install @types/ws # For TypeScript projects