There Was an Error Connecting to a Websocket. Try Your Request Again.
past Janitha Tennakoon
How to build real-time applications using WebSockets with AWS API Gateway and Lambda
Recently AWS has appear the launch of a widely-requested feature: WebSockets for Amazon API Gateway. With WebSockets, we are able to create a ii-fashion communication line which can be used in many scenarios like real-time applications. This brings up the question: what are existent-time applications? Then let's outset reply that question.
Most of the applications that are currently operational use customer-server architecture. In client-server compages, the client sends the requests over the Internet using network communication and so the server processes that request and sends the response dorsum to the client.
Here you lot can see that it is the client that starts off the communication with the server. Then outset the customer initiates the communication and the server responds to the request sent by the server. So what if the server wants to start off the communication and push responses without the client requesting them get-go? That is where existent-fourth dimension applications come into the play.
Real-time applications are applications where the server gets the ability to push to the clients without the client requesting data first. Presume we have a conversation application where two conversation clients can communicate via a server. In this situation, information technology is a waste material if all the chat clients request data from the server like every second. What is more efficient is if the server sends data to client chat applications when a chat is received. This functionality can be done through real-time applications.
Amazon announced that they are going to support WebSockets in API Gateway at AWS re:Invent 2018. Later on in December, they launched it in the API Gateway. So now using AWS infrastructure we are able to create real-time applications using API Gateway.
In this postal service, nosotros are going to create a simple chat awarding using API Gateway WebSockets. Before we starting time implementing our chat awarding, there are some concepts that we demand to understand regarding existent-time applications and API Gateway.
WebSocket API Concepts
A WebSocket API is composed of one or more than routes. A road option expression is there to determine which route a particular inbound request should use, which will be provided in the inbound request. The expression is evaluated against an inbound request to produce a value that corresponds to one of your route's routeKey values. For example, if our JSON letters contain a property call activity, and you want to perform different actions based on this property, your road selection expression might be ${asking.trunk.action}
.
For example: if your JSON message looks similar {"activeness" : "onMessage" , "message" : "Hello everyone"}, then the onMessage route will exist called for this request.
Past default, there are three routes which are already defined in the WebSocket API. In add-on to the below-mentioned routes, we tin add together custom routes for our needs.
- $default — Used when the route pick expression produces a value that does not match any of the other route keys in your API routes. This can be used, for example, to implement a generic error handling mechanism.
- $connect — The associated route is used when a client commencement connects to your WebSocket API.
- $disconnect — The associated route is used when a client disconnects from your API.
Once a device is successfully continued through WebSocket API, the device volition exist allocated with a unique connection id. This connection id will exist persisted throughout the lifetime if the connectedness. To send messages back to the device we need to use the following POST asking using the connection id.
POST https://{api-id}.execute-api.u.s.a.-east 1.amazonaws.com/{phase}/@connections/{connection_id}
Implementing conversation application
After learning the basic concepts of the WebSocket API, let us await at how we tin can create a existent-time application using WebSocket API. In this mail, we are going to implement a simple chat awarding using WebSocket API, AWS LAmbda and DynamoDB. The following diagram shows the architecture of our real-time application.
In our application, devices will be connected to the API Gateway. When a device gets continued, a lambda function will save the connection id in a DynamoDB table. In an instance where we want to send a message dorsum to the device, another lambda role will recall the connection id and POST data dorsum to the device using a callback URL.
Creating WebSocket API
In lodge to create the WebSocket API, nosotros need showtime go to Amazon API Gateway service using the console. In in that location cull to create new API. Click on WebSocket to create a WebSocket API, give an API proper noun and our Road Pick Expression. In our case add together $request.body.action equally our pick expression and hit Create API.
After creating the API we will be redirected to the routes page. Here we can see already predefined three routes: $connect, $disconnect and $default. We will also create a custom route $onMessage. In our architecture, $connect and $disconnect routes achieve the following tasks:
- $connect — when this route is chosen, a Lambda function will add the connection id of the connected device to DynamoDB.
- $disconnect — when this road is called, a Lambda office volition delete the connection id of the asunder device from DynamoDB.
- onMessage — when this road is called, the message body volition be sent to all the devices that are continued at the time.
Before adding the route according to the above, we need to exercise four tasks:
- Create a DynamoDB table
- Create connect lambda office
- Create disconnect lambda function
- Create onMessage lambda function
Start, permit u.s. create the DynamoDB tabular array. Go to DynamoDB service and create a new tabular array chosen Chat. Add chief key as 'connectionid'.
Next, let'south create the connect Lambda function. To create the Lambda function, become to Lambda services and click create part. Select Writer from scratch and requite the name equally 'ChatRoomConnectFunction' and a part with necessary permissions. (The role should take the permission to get, put and delete items from DynamoDB, telephone call API calls in API gateway.)
In the code of the lambda function add the following code. This code will add the connection id of the connected device to the DynamoDB tabular array that we have created.
exports.handler = (consequence, context, callback) => { const connectionId = effect.requestContext.connectionId; addConnectionId(connectionId).and so(() => { callback(null, { statusCode: 200, }) });}
part addConnectionId(connectionId) { return ddb.put({ TableName: 'Conversation', Item: { connectionid : connectionId }, }).hope();}
Side by side, let united states of america create the disconnect lambda function also. Using the same steps create a new lambda role named
'ChatRoomDonnectFunction'. Add the following code to the office. This lawmaking will remove the connection id from the DynamoDB table when a device gets disconnected.
const AWS = require('aws-sdk');const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = (event, context, callback) => { const connectionId = event.requestContext.connectionId; addConnectionId(connectionId).then(() => { callback(nada, { statusCode: 200, }) });}
office addConnectionId(connectionId) { return ddb.delete({ TableName: 'Chat', Fundamental: { connectionid : connectionId, }, }).hope();}
Now nosotros take created the DynamoDB table and two lambda functions. Earlier creating the third lambda function, let us become back again to API Gateway and configure the routes using our created lambda functions. First, click on $connect road. Equally integration type, select Lambda function and select the ChatRoomConnectionFunction.
We can do the same on $disconnect route too where the lambda part will be ChatRoomDisconnectionFunction:
Now that we accept configured our $connect and $disconnect routes, nosotros can actually test whether out WebSocket API is working. To do that we must first to deploy the API. In the Actions push button, click on Deploy API to deploy. Requite a stage name such every bit Test since we are only deploying the API for testing.
Afterward deploying, we will be presented with two URLs. The first URL is called WebSocket URL and the 2nd is called Connection URL.
The WebSocket URL is the URL that is used to connect through WebSockets to our API by devices. And the second URL, which is Connection URL, is the URL which we will utilise to call back to the devices which are connected. Since we have not yet configured call up to devices, permit's first only test the $connect and $disconnect routes.
To telephone call through WebSockets nosotros tin can apply the wscat tool. To install information technology, we demand to just effect the npm install -g wscat
control in the control line. After installing, we tin utilize the tool using wscat command. To connect to our WebSocket API, issue the following control. Make sure to replace the WebSocket URL with the correct URL provided to you.
wscat -c wss://bh5a9s7j1e.execute-api.us-east-1.amazonaws.com/Test
When the connection is successful, a continued message will be displayed on the concluding. To cheque whether our lambda function is working, we can go to DynamoDB and wait in the table for the connection id of the continued terminal.
Every bit above, we tin test the disconnect as well by pressing CTRL + C which volition simulate a disconnection.
Now that we accept tested our 2 routes, let u.s. look into the custom road onMessage. What this custom route will exercise is information technology will go a message from the device and transport the message to all the devices that are continued to the WebSocket API. To achieve this we are going to need another lambda function which volition query our DynamoDB table, get all the connection ids, and ship the bulletin to them.
Permit's showtime create the lambda function in the same way nosotros created other 2 lambda functions. Name the lambda part ChatRoomOnMessageFunction and re-create the following code to the function code.
const AWS = crave('aws-sdk');const ddb = new AWS.DynamoDB.DocumentClient();require('./patch.js');
allow send = undefined;function init(event) { panel.log(upshot) const apigwManagementApi = new AWS.ApiGatewayManagementApi({ apiVersion: '2018-11-29', endpoint: event.requestContext.domainName + '/' + event.requestContext.phase }); send = async (connectionId, data) => { look apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: `Echo: ${information}` }).promise(); }}
exports.handler = (event, context, callback) => { init(event); allow bulletin = JSON.parse(event.torso).bulletin getConnections().then((data) => { console.log(data.Items); information.Items.forEach(function(connection) { console.log("Connection " +connection.connectionid) transport(connection.connectionid, message); }); }); return {}};
part getConnections(){ render ddb.scan({ TableName: 'Chat', }).promise();}
The above code will browse the DynamoDB to go all the available records in the table. For each record, information technology will POST a message using the Connection URL provided to u.s.a. in the API. In the code, we expect that the devices will send the message in the attribute named 'bulletin' which the lambda function volition parse and send to others.
Since WebSockets API is nonetheless new there are some things nosotros demand to do manually. Create a new file named patch.js and add the following code inside information technology.
require('aws-sdk/lib/node_loader');var AWS = require('aws-sdk/lib/core');var Service = AWS.Service;var apiLoader = AWS.apiLoader;
apiLoader.services['apigatewaymanagementapi'] = {};AWS.ApiGatewayManagementApi = Service.defineService('apigatewaymanagementapi', ['2018-11-29']);Object.defineProperty(apiLoader.services['apigatewaymanagementapi'], '2018-eleven-29', { get: function get() { var model = { "metadata": { "apiVersion": "2018-11-29", "endpointPrefix": "execute-api", "signingName": "execute-api", "serviceFullName": "AmazonApiGatewayManagementApi", "serviceId": "ApiGatewayManagementApi", "protocol": "rest-json", "jsonVersion": "one.one", "uid": "apigatewaymanagementapi-2018-11-29", "signatureVersion": "v4" }, "operations": { "PostToConnection": { "http": { "requestUri": "/@connections/{connectionId}", "responseCode": 200 }, "input": { "type": "construction", "members": { "Data": { "blazon": "blob" }, "ConnectionId": { "location": "uri", "locationName": "connectionId" } }, "required": [ "ConnectionId", "Information" ], "payload": "Data" } } }, "shapes": {} } model.paginators = { "pagination": {} } return model; }, enumerable: true, configurable: truthful});
module.exports = AWS.ApiGatewayManagementApi;
I took the to a higher place code from this article. The functionality of this code is to automatically create the Callback URL for our API and ship the POST request.
At present that we accept created the lambda function we can go ahead and create our custom route in API Gateway. In the New Route Central, add 'OnMessage' equally a route and add the custom route. As configurations were done for other routes, add together our lambda function to this custom route and deploy the API.
Now we have completed our WebSocket API and we can fully test the application. To test that sending messages works for multiple devices, we can open and connect using multiple terminals.
Later connecting, issue the following JSON to transport messages:
{"action" : "onMessage" , "message" : "How-do-you-do everyone"}
Hither, the action is the custom route nosotros defined and the message is the data that need to be sent to other devices.
That is it for our simple chat application using AWS WebSocket API. Nosotros have not actually configured the $defalut route which is called on every occasion where at that place no route is found. I volition leave the implementation of that route to you. Thanks and see you lot in some other post. :)
Larn to lawmaking for complimentary. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Go started
Source: https://www.freecodecamp.org/news/real-time-applications-using-websockets-with-aws-api-gateway-and-lambda-a5bb493e9452/
0 Response to "There Was an Error Connecting to a Websocket. Try Your Request Again."
Post a Comment