Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a WebSocket message from a POST request handler in express

I have an Express server that listens for webhook events from an external API. When it received these events, I want the handler for that http request to send a message to a WebSocket client. Here is some basic code to illustrate what I mean

The external API will send a HTTP POST request to an endpoint on my Express server, lets say it looks like this:

app.post('/external-api', (req, res) => {

    // webhook payload will be in req.body
})

In that handler for /external-api I'd like to send a message to a client who's connected to the server via WebSocket. As of right now, I'm using the npm ws library, so I want the logic to look something like this

app.post('/external-api', (req, res) => {

    ws.broadcast(req.body);
})

Is there a way to do this? I'm open to using other libraries but I just need a way to send a message to a WebSocket client from a HTTP POST request handler in Express.

like image 646
Gautam Jethwani Avatar asked Jul 26 '20 11:07

Gautam Jethwani


People also ask

How do I send a WebSocket message?

To send a message through the WebSocket connection you call the send() method on your WebSocket instance; passing in the data you want to transfer. socket. send(data); You can send both text and binary data through a WebSocket.

Is WebSocket a post or get?

Yes, a webSocket connection will always start with a GET request, not a POST or any other method.

How do you interact with WebSockets?

In order to communicate using the WebSocket protocol, you need to create a WebSocket object; this will automatically attempt to open the connection to the server. The URL to which to connect; this should be the URL to which the WebSocket server will respond.

Can a WebSocket call an API?

You can't call an HTTP API from web socket. You can call a web socket API from a web socket. That mostly means you send some specific message over web socket to the server, and the server sends something specific back.

How does WebSockets send and receive messages?

WebSockets - Send & Receive Messages. The Message event takes place usually when the server sends some data. Messages sent by the server to the client can include plain text messages, binary data, or images. Whenever data is sent, the onmessage function is fired. This event acts as a client's ear to the server.

How do I listen to WebSockets on an express server?

Here's how you can use the ws package to listen to websockets on an Express server. The ws package supports native Node.js HTTP servers. Conveniently, Express' listen () function returns a native Node.js HTTP server.

How to handle the get and POST request in Express Framework?

//To access POST variable use req.body ()methods. In this way, you can handle the GET and POST request in the Express framework. To demonstrate this, I am going to code one simple log-in System which will use GET request to serve HTML page to client and POST request from the client to send user name and password to Server.

What is the difference between GET request and POST request?

POST requests requests are different from GET requests because POST requests are allowed to send data in the HTTP request body. For example, the below code sends an HTTP POST request with a JSON object in the request body:


1 Answers

Here is an example:

index.ts:

import express from 'express';
import WebSocket from 'ws';
import http from 'http';
import path from 'path';
import faker from 'faker';

const app = express();
const port = 3000;
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws: WebSocket) => {
  console.log('establish websocket connection');
  ws.on('message', (message) => {
    console.log('received: %s', message);
  });
});

app.get('/client/:id', (req, res) => {
  res.sendFile(path.resolve(__dirname, `./public/client-${req.params.id}.html`));
});

app.get('/external-api', (req, res) => {
  wss.clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(faker.internet.email());
    }
  });
  res.sendStatus(200);
});

server.listen(port, () => console.log(`http server is listening on http://localhost:${port}`));

client-1.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>client 1</title>
  </head>
  <body>
    <p>client 1</p>
    <button id="test">Test</button>
    <script>
      (function() {
        window.onload = function() {
          const socket = new WebSocket('ws://localhost:3000');

          // Connection opened
          socket.addEventListener('open', function(event) {
            socket.send('Hello Server! Client - 1');
          });

          // Listen for messages
          socket.addEventListener('message', function(event) {
            console.log('Message from server ', event.data);
          });

          const btn = document.getElementById('test');
          btn.addEventListener('click', async () => {
            try {
              const res = await fetch('http://localhost:3000/external-api');
              console.log(res);
            } catch (error) {
              console.log(error);
            }
          });
        };
      })();
    </script>
  </body>
</html>

client-2.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>client 2</title>
  </head>
  <body>
    <p>client 2</p>
    <button id="test">Test</button>
    <script>
      (function() {
        window.onload = function() {
          const socket = new WebSocket('ws://localhost:3000');

          // Connection opened
          socket.addEventListener('open', function(event) {
            socket.send('Hello Server! Client - 2');
          });

          // Listen for messages
          socket.addEventListener('message', function(event) {
            console.log('Message from server ', event.data);
          });

          const btn = document.getElementById('test');
          btn.addEventListener('click', async () => {
            try {
              const res = await fetch('http://localhost:3000/external-api');
              console.log(res);
            } catch (error) {
              console.log(error);
            }
          });
        };
      })();
    </script>
  </body>
</html>

Now, click the button of client 1, send HTTP request to /external-api.

The console logs of client 1:

enter image description here

The console logs of client 2:

enter image description here

The logs of server:

http server is listening on http://localhost:3000
establish websocket connection
received: Hello Server! Client - 1
establish websocket connection
received: Hello Server! Client - 2

As you can see, the server broadcast fake emails to client 1 and client 2.

like image 137
slideshowp2 Avatar answered Nov 15 '22 03:11

slideshowp2