Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use socket.io with node js rest api?

I want to build a web application with node js rest api as backend and angular 4 as frontend. I want to use socket io for real time. How to use socket io with node js rest api?

like image 297
Vyankatesh Charakpalli Avatar asked Aug 10 '26 07:08

Vyankatesh Charakpalli


1 Answers

So I was looking for a discussion about this, but I just implemented something and I wanted to share and see if I can get any feedback. I think socket.io is a great way to implement APIs, especially for bidirectional communication, and realtime communication. Here's a start:

On the server side created this file - socket-api-server:

"use strict";

const serverIo = require("socket.io");
const server = serverIo.listen(process.env.PORT || 8000);

const api_keys=JSON.parse(process.env.SOCKET_API_KEYS|| "[]");

/**
 * Server Side
 * 
 */

function socketAPIServer(apis){
    server.on("connection", (socket) => {
        // this must be first - to block unauthenticated access to the APIs
        socket.use((packet,next)=>{
            if(socket.auth) return next();
            else if(packet[0]==="authenticate" && api_keys.includes(packet[1])){ 
                socket.auth=true;
                socket.emit("authenticated")
                return next();
            }
            else return next(new Error("unauthorized"));
        })
        socket.on("disconnect", () => {
            delete socket.auth;
        });
        apis.forEach(api=>{
            socket.on(api.name,api.func)
        })
    });
}

module.exports=socketAPIServer;

Then I have API's in a file - but you could do them as separate files:

const APIs=[
    {   name: "api_name", func: (p1, p2,..., cb)=>{
            cb(figure out what to send )
        }
    },
    {   name: "another_api_name", func: (p1,cb)=>{
            cb( calculate something from p1)
        }
    }
];

socketAPIServer(APIs);

Then on the client side I have a file that looks like this:

const clientIo = require("socket.io-client");

// ensure ENV keys
if (!process.env.API_KEY) {
    console.error("API_KEY needed.  On bash use: export API_KEY=\"your-key-here\" or add it to your .bashrc file")
    process.exit();
}

// ensure ENV keys
if (!process.env.API_URL) {
    console.error("API_URL needed.  On bash use: export API_URL=\"your-key-here\" or add it to your .bashrc file")
    process.exit();
}

const ioClient = clientIo.connect(process.env.API_URL);
var authenticated=false;
var queued=[];

ioClient.on('connect',()=>{
    console.info("client connected", ioClient.id);
    ioClient.emit('authenticate', process.env.API_KEY);
    ioClient.on("authenticated",()=>{
        authenticated=true;
        while(queued.length) queued.shift()();
    })
});

function socketAPI(...args) {
    if(args[0]==='disconnect') 
        return ioClient.close();
    if(!authenticated) queued.push(()=>ioClient.emit(...args))
    else
        ioClient.emit(...args)
}

module.exports=socketAPI;

Then you can use it this way:

    var socketAPI=require('./socketAPI');

    socketAPI("api_name",p1,p2,results=>{
        console.info(results);
    })

for testing set

export API_URL="http://localhost:8000" 
export API_KEY="a long random string"
export API_KEYS="[\"a long random string\"]"

This could probably be expanded on, but it's a start. Please let me know if this is useful, or if there is somewhere this kind of discussion is happening. :-)

like image 155
David Fridley Avatar answered Aug 12 '26 20:08

David Fridley