Websocket - API Architecture Style Every Developer Must Know
WebSocket APIs offer APIs that the client can access through the WebSocket protocol. Unlike REST and HTTP APIs, WebSocket APIs allow bidirectional communications. WebSocket APIs are often used in real-time applications such as chat applications, collaboration platforms, multiplayer games, and financial trading platforms.
For now, WebSocket APIs are offered only with a Regional endpoint type. The APIs must be accessed over the internet. Using a private integration, requests through APIs can be routed to EC2 instances or VPC resources through an NLB privately. You can perform TLS termination on a TLS listener of the NLB, or pass the TLS traffic through to the target group instances. If the TLS termination happens on the target group instances, you can implement client certificates generated by API Gateway to enhance security.
In a typical client-server architecture where web applications communicate with API endpoints, the API gateway’s timeout limitation poses a significant challenge. As timeouts are typically set to a maximum of 1 minute, it becomes crucial to find a solution that avoids undermining the users’ experience while ensuring optimal backend performance.
While asynchronous API calls may seem like a viable option, this method introduces the need for repetitive polling of another API endpoint to determine data readiness following transformations. In addition, as the web app scales, excessive polling burdens the server unnecessarily, resulting in performance issues like slow response times, disruptive timeouts, and increased costs. To efficiently address these challenges, we will explore how WebSockets can offer a better alternative to asynchronous API calls.
WebSocket APIs in API Gateway
In your WebSocket API, incoming JSON messages are directed to backend integrations based on routes that you configure. (Non-JSON messages are directed to a $default
route that you configure.) A route includes a route key, which is the value that is expected once a route selection expression is evaluated. The routeSelectionExpression
is an attribute defined at the API level. It specifies a JSON property that is expected to be present in the message payload. For more information about route selection expressions.
In API Gateway you can create a WebSocket API as a stateful frontend for an AWS service (such as Lambda or DynamoDB) or for an HTTP endpoint. The WebSocket API invokes your backend based on the content of the messages it receives from client apps.Unlike a REST API, which receives and responds to requests, a WebSocket API supports two-way communication between client apps and your backend. The backend can send callback messages to connected clients.
For example, if your JSON messages contain an action
property, and you want to perform different actions based on this property, your route selection expression might be ${request.body.action}
. Your routing table would specify which action to perform by matching the value of the action
property against the custom route key values that you have defined in the table.
WebSockets operatae according to the following processes
Establish a connection and upgrading to the WebSocket protocol
To initiate WebSockets, the client and server must first establish a connection. The client sends a HTTP handshake request, incorporating a header that signals the intent to upgrade to the WebSocket protocol (HTTP Status 101). Upon receiving this request, the server responds with a HTTP handshake response, confirming the acceptance of the upgrade. This response contains a distinct header indicating the successful transition to a WebSocket protocol.
Sending and receiving data
Once the WebSocket connection is established, real-time data transmission becomes possible between client and server. Data is exchanged in frames consisting of a header and a payload. The header carries essential frame details, such as the length and type, while the payload holds the actual data to be transmitted.
Closing the connection
When either the client or server decides to terminate the WebSocket connection, a closing frame is sent. The recipient responds with its own closing frame, leading to the closure of the connection.
Interfaces
WebSocket
– The primary interface for connecting to a WebSocket server and then sending and receiving data on the connection.- CloseEvent – The event sent by the WebSocket object when the connection closes.
- MessageEvent –The event sent by the WebSocket object when a message is received from the server.
1. WebSocket
The WebSocket
object provides the API for creating and managing a WebSocket connection to a server, as well as for sending and receiving data on the connection.
To construct a WebSocket
, use the WebSocket()
constructor.
Constructor
WebSocket()
Returns a newly created WebSocket
object.
Instance properties
WebSocket.binaryType
The binary data type used by the connection.
WebSocket.bufferedAmount
Read only – The number of bytes of queued data.
WebSocket.extensions
Read only – The extensions selected by the server.
WebSocket.protocol
Read only – The sub-protocol selected by the server.
WebSocket.readyState
Read only – The current state of the connection.
WebSocket.url
Read only – The absolute URL of the WebSocket.
Instance methods
WebSocket.close()
–- Closes the connection.
WebSocket.send()
–- Enqueues data to be transmitted.
Events
Listen to these events using addEventListener()
or by assigning an event listener to the oneventname
property of this interface.
close
- Fired when a connection with a
WebSocket
is closed. Also available via theonclose
property error
- Fired when a connection with a
WebSocket
has been closed because of an error, such as when some data couldn’t be sent. Also available via theonerror
property. message
- Fired when data is received through a
WebSocket
. Also available via theonmessage
property. open
- Fired when a connection with a
WebSocket
is opened. Also available via theonopen
property.
// Send text to all users through the server
function sendText() {
// Construct a msg object containing the data the server needs to process the message from the chat client.
const msg = {
type: "message",
text: document.getElementById("text").value,
id: clientID,
date: Date.now(),
};
// Send the msg object as a JSON-formatted string.
exampleSocket.send(JSON.stringify(msg));
// Blank the text input element, ready to receive the next line of text from the user.
document.getElementById("text").value = "";
}
exampleSocket.onmessage = (event) => {
console.log(event.data);
};
2. CloseEvent
A CloseEvent
is sent to clients using WebSockets when the connection is closed. This is delivered to the listener indicated by the WebSocket
object’s onclose
attribute.
Constructor
CloseEvent()
Creates a new
CloseEvent
.
Instance properties
This interface also inherits properties from its parent, Event
.
CloseEvent.code
Read onlyReturns an
unsigned short
containing the close code sent by the server.CloseEvent.reason
Read onlyReturns a string indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.
CloseEvent.wasClean
Read onlyReturns a boolean value that Indicates whether or not the connection was cleanly closed.
Instance methods
This interface also inherits methods from its parent, Event
.
3. MessageEvent
The MessageEvent
interface represents a message received by a target object.
This is used to represent messages in:
- Server-sent events (see
EventSource.message_event
). - Web sockets (see the
onmessage
property of the WebSocket interface). - Cross-document messaging (see
Window.postMessage()
andWindow.message_event
). - Channel messaging (see
MessagePort.postMessage()
andMessagePort.message_event
). - Cross-worker/document messaging (see the above two entries, but also
Worker.postMessage()
,Worker.message_event
,ServiceWorkerGlobalScope.message_event
, etc.) - Broadcast channels (see
BroadcastChannel.postMessage()
) andBroadcastChannel.message_event
). - WebRTC data channels (see
onmessage
).
The action triggered by this event is defined in a function set as the event handler for the relevant message
event (e.g. using an onmessage
handler as listed above).
Constructor
MessageEvent()
Creates a new
MessageEvent
.
Instance properties
This interface also inherits properties from its parent, Event
.
MessageEvent.data
Read onlyThe data sent by the message emitter.
MessageEvent.origin
Read onlyA string representing the origin of the message emitter.
MessageEvent.lastEventId
Read onlyA string representing a unique ID for the event.
MessageEvent.source
Read onlyA
MessageEventSource
(which can be a WindowProxy,MessagePort
, orServiceWorker
object) representing the message emitter.MessageEvent.ports
Read onlyAn array of
MessagePort
objects representing the ports associated with the channel the message is being sent through (where appropriate, e.g. in channel messaging or when sending a message to a shared worker).
Instance methods
This interface also inherits methods from its parent, Event
.
initMessageEvent()
DeprecatedInitializes a message event. Do not use this anymore — use the
MessageEvent()
constructor instead.
Tools
- AsyncAPI: A specification for describing event-driven architectures based on protocols like WebSocket. You can use it to describe WebSocket-based APIs just as you would describe REST APIs with the OpenAPI specification.
- HumbleNet: A cross-platform networking library that works in the browser. It consists of a C wrapper around WebSockets and WebRTC that abstracts away cross-browser differences, facilitating the creation of multi-user networking functionality for games and other apps.
- µWebSockets: Highly scalable WebSocket server and client implementation for C++11 and Node.js.
- Socket.IO: A long polling/WebSocket based third party transfer protocol for Node.js.
- SocketCluster: A pub/sub WebSocket framework for Node.js with a focus on scalability.
- WebSocket-Node: A WebSocket server API implementation for Node.js.
- Total.js: Web application framework for Node.js (Example: WebSocket chat)
- Faye: A
WebSocket
(two-ways connections) and EventSource (one-way connections) for Node.js Server and Client. - SignalR: SignalR will use WebSockets under the covers when it’s available, and gracefully fallback to other techniques and technologies when it isn’t, while your application code stays the same.
- Caddy: A web server capable of proxying arbitrary commands (stdin/stdout) as a websocket.
- ws: a popular WebSocket client & server library for Node.js.
- jsonrpc-bidirectional: Asynchronous RPC which, on a single connection, may have functions exported on the server and, and the same time, on the client (client may call server, server may also call client).
- cowboy: Cowboy is a small, fast and modern HTTP server for Erlang/OTP with WebSocket support.
- ZeroMQ: ZeroMQ is embeddable networking library that carries messages across in-process, IPC, TCP, UDP, TIPC, multicast and WebSocket.
- WebSocket King: A client tool to help develop, test and work with WebSocket servers.
- PHP WebSocket Server: Server written in PHP to handle connections via websockets wss:// or ws://and normal sockets over ssl:// ,tcp://
- Channels: Django library that adds support for WebSockets (and other protocols that require long running asynchronous connections).
- Flask-SocketIO: gives Flask applications access to low latency bi-directional communications between the clients and the server.
- Gorilla WebSocket: Gorilla WebSocket is a Go implementation of the WebSocket protocol.
Pingback: Amazon VPC Astounding concise virtual-private-cloud 2024