WebSockets Commercial
Understanding the WebSocket Protocol
WebSocket is a communication protocol that provides full-duplex communication channels over a single, long-lived TCP connection. Unlike traditional HTTP request-response patterns, WebSocket enables real-time, bidirectional communication between clients and servers.
Key Features of WebSocket
- Full-Duplex Communication: Both client and server can send messages independently at any time
- Persistent Connection: Connection remains open, eliminating the overhead of establishing new connections for each message
- Low Latency: Ideal for real-time applications like chat, live notifications, and streaming data
- Efficient: Reduced overhead compared to HTTP polling or long-polling techniques
Common Use Cases
- Real-time chat applications
- Live order tracking and notifications
- Financial trading platforms
- Collaborative editing tools
- IoT device communication
- Gaming applications
Specifying WebSocket APIs with AsyncAPI
Specmatic-async uses the AsyncAPI 3.0.0 specification to define WebSocket contracts. AsyncAPI is to event-driven APIs what OpenAPI is to REST APIs.
Basic Structure
Here's how to define a WebSocket API using AsyncAPI:
asyncapi: 3.0.0
info:
title: Order API
version: 1.0.0
servers:
wsServer:
host: 'ws://localhost:8080'
protocol: ws
description: Websocket server
Defining Channels
Channels represent the communication paths in your WebSocket API. Each channel has an address (endpoint) and associated messages:
channels:
NewOrderPlaced:
address: new-orders
servers:
- $ref: '#/servers/wsServer'
messages:
placeOrder.message:
$ref: '#/components/messages/OrderRequest'
OrderInitiated:
address: wip-orders
servers:
- $ref: '#/servers/wsServer'
messages:
processOrder.message:
$ref: '#/components/messages/Order'
Defining Operations
Operations describe the actions that can be performed on channels:
operations:
placeOrder:
action: receive # Server receives this message
channel:
$ref: '#/channels/NewOrderPlaced'
messages:
- $ref: '#/channels/NewOrderPlaced/messages/placeOrder.message'
reply: # Server replies on this channel
channel:
$ref: '#/channels/OrderInitiated'
messages:
- $ref: '#/channels/OrderInitiated/messages/processOrder.message'
Action Types:
receive: Server receives messages from clientssend: Server sends messages to clients
Defining Message Schemas
Define the structure and validation rules for your messages:
components:
messages:
OrderRequest:
name: OrderRequest
title: An order request
contentType: application/json
payload:
type: object
required:
- id
- orderItems
properties:
id:
type: integer
orderItems:
type: array
items:
type: object
properties:
id:
type: integer
name:
type: string
quantity:
type: integer
price:
type: number
required:
- id
- name
- quantity
- price
examples:
- name: NEW_ORDER
payload:
id: 10
orderItems:
- id: 1
name: Macbook
quantity: 1
price: 2000
Contract Testing with Specmatic-Async
Specmatic-async enables contract-driven testing for WebSocket APIs, ensuring both producers and consumers adhere to the AsyncAPI specification.
For a complete working example of Websocket contract testing with Specmatic-Async, refer to the specmatic-websocket-sample project.
Project Setup
1. Create Specmatic Configuration
Create a specmatic.yaml file in your project root:
version: 2
contracts:
- provides:
- specification/spec.yaml
This configuration tells Specmatic where to find your AsyncAPI specification file.
2. Directory Structure
Organize your project as follows:
project-root/
├── specmatic.yaml
├── specification/
│ ├── spec.yaml # AsyncAPI specification
│ └── overlay.yaml # Specmatic overlays (optional)
├── package.json
└── ws-server.js # Your WebSocket server implementation
Running Contract Tests
Using Docker
The recommended approach is to use the Specmatic Docker image:
const { execSync } = require("child_process");
const cwd = process.cwd();
execSync(
`docker run --rm --network host \
-v "${cwd}/specmatic.yaml:/usr/src/app/specmatic.yaml" \
-v "${cwd}/specification:/usr/src/app/specification" \
specmatic/enterprise test \
--overlay=specification/overlay.yaml`,
{ stdio: "inherit" }
);
npm Script
Add to your package.json:
{
"scripts": {
"contractTest": "node contract-test-runner.js"
}
}
Run the tests:
npm run contractTest
Manually testing
You can also run the application manually and use the docker command as follows:
docker run --rm --network host \
-v "${cwd}/specmatic.yaml:/usr/src/app/specmatic.yaml" \
-v "${cwd}/specification:/usr/src/app/specification" \
specmatic/enterprise test \
--overlay=specification/overlay.yaml
What Gets Tested
Specmatic-async automatically validates:
✅ Message Structure: Ensures messages conform to the defined schema
✅ Required Fields: Validates all required fields are present
✅ Data Types: Checks field types match the specification
✅ Channel Routing: Verifies messages are sent/received on correct channels
✅ Request-Reply Patterns: Validates reply messages match expected responses
✅ Enum Values: Ensures enum fields contain valid values
✅ Triggers & Side Effects: Validates HTTP triggers and side effects when configured
Example Test Flow
For a complete order placement flow:
-
Client sends order request →
/new-orderschannel- Specmatic validates the message structure
-
Server processes and replies →
/wip-orderschannel- Specmatic validates the reply matches the contract
- Checks the order status is "INITIATED"
-
Server sends acceptance →
/accepted-orderschannel- HTTP trigger initiates the message
- Specmatic validates the broadcast message
-
Client requests delivery →
/out-for-delivery-orderschannel- Specmatic validates the request
- Side effect validation confirms order status change
Benefits of Contract Testing WebSocket APIs
- Design-First Development: Define the contract before implementation
- Producer-Consumer Alignment: Both sides work from the same specification
- Automated Validation: No manual testing of message formats
- Regression Prevention: Changes breaking the contract are caught immediately
- Documentation: AsyncAPI spec serves as living documentation
- Mock Generation: Generate mock servers from specifications
- CI/CD Integration: Run contract tests in your pipeline
Best Practices
- Version Your Specifications: Track changes to your AsyncAPI files
- Use Examples: Provide realistic examples in your message definitions
- Organize Channels Logically: Group related operations together
- Define Clear Operation Names: Use descriptive names for operations
- Document Edge Cases: Use overlays to test error scenarios
- Run Tests in CI/CD: Integrate contract tests into your deployment pipeline
- Keep Specs DRY: Use
$refto reuse common schemas and messages