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?
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. :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With