How to call node api response in socket.io server - javascript

Scenario: Creating a Node API (GET) calling that API in socket.io Node server and calling this socket server in angular client.
What i have done: Created a node API for get request and post and created a socket server I tried to consume the app.
Issues: 1. I tried to consume the API but was unable to get the data in the socket server and 2. If it works, also how can i get the socket data on button click in angular application?
Note: I'm running Node API on 3000 server and running socket server on 3001.
Below is my code
Node api code runnning on 3000 port:
const express = require('express')
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express()
const port = 3000
let books = [{
"isbn": "9781593275846",
"title": "Eloquent JavaScript, Second Edition",
"author": "Marijn Haverbeke",
"publish_date": "2014-12-14",
"publisher": "No Starch Press",
"numOfPages": 472,
}];
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.post('/book', (req, res) => {
const book = req.body;
// output the book to the console for debugging
console.log(book);
books.push(book);
res.send('Book is added to the database');
});
app.get('/book', (req, res) => {
res.json(books);
});
app.listen(port, () => console.log(`Hello world app listening on port ${port}!`));
Socket .io server running on 3001
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
const apiUrl="http://localhost:3000/book"
io.on('connection', function (socket) {
socket.on('getBanners', function(data){
request.get(apiUrl,function (error, response, body){
console.log(body)
socket.emit('result', {res:JSON.parse(body)})
})
});
});
http.listen(3001, function(){
console.log('listening on *:3001');
});
Note: Node API server --> socketio server (not client)

I wouldn't recommend going by that design you have.
Unless there is a very specific/important reason to have the socket.io server on a different port than the HTTP server, I would recommend having your socket.io server upgraded from the HTTP server itself.
eg.
In bin/www:
const { initSocketIOServer } = require('../socket-server');
const port = normalizePort(process.env.PORT || '3001');
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
initSocketIOServer(server);
In socket.server.js
module.exports.initSocketServer = (server) => {
io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('client connected');
socket.on('getBanners', (event) => {
// handle getBanners event here
});
});
};
However, going by your example, if you really need to make a request to the HTTP server to fetch data, you might want to use the HTTP library:
socket.on('getBanners', (event) => {
http.get({
hostname: 'localhost',
port: 3000,
path: '/book',
agent: false // Create a new agent just for this one request
}, (res) => {
// Do stuff with response, eg.
const socketResponse = processBooks(book);
socket.emit('result', socketResponse);
});
});

You can use any node package for requests like request https://github.com/request/request
here

Related

I want to build my own webhook dispatch server using node js?

I am trying to build a webhook server using node js. If any user sets their server URL as a hook using API provided by me, then my webhook server should respond to that user server.
I got this idea from the Facebook Messenger Chatbot application which uses the same approach.
Server 1 - My Server
const express = require("express");
const axios = require("axios");
const app = express();
const PORT = 3000;
/* Set Middleware to Express App */
app.use(express.json());
// Routes
app.post("/handle-webhooks", (req, res) => {
const body = {"id": "1", "message": "hello"};
const headers = {
'Content-Type': "application/json",
}
const clientWebhookUrl = "http://localhost:8093/webhook2" // This will be different for each client
axios.post(clientWebhookUrl, body, {headers})
return res.sendStatus(200);
})
app.post("/set-webhook", (req,res) => {
const clientWebhookUrl = req.url;
// This URL will be saved to database
return res.sendStatus(200)
}
/* Listen Server */
app.listen(PORT, () => {
console.log(`App is listening on port ${PORT}.`);
})
Server 2 - My Client 1 Server
Using postman, the Client will make a post request to http://localhost:3000/set-webhook and set the webhook2 endpoint of his web server as a webhook URL to receive a response from my server.
const express = require("express");
const axios = require("axios");
const app = express();
const PORT = 8093;
/* Set Middleware to Express App */
app.use(express.json());
// Routes
app.post("/webhook2", (req, res) => {
const body = req.body; // receives {"id": "1", "message": "hello"}
return res.status(200).send(body);
})
/* Listen Server */
app.listen(PORT, () => {
console.log(`App is listening on port ${PORT}.`);
})
Is the above approach is correct for doing this task? or do I need to add more complex code for this?
Thanks.

Implementing socket.io in mongoDB and Angular it is throwing errors Cannot GET /socket.io/

I am developing an angular application which I need to use notifications for example.
I have a user which can add friends and then I can sent a friend request as in facebook and then the other user will be notificate in realtime for example You have one new notification, this user wants to be friends.
If anyone has better idea than socket.io I am free to listen and to learn
The problem it is that I get everytime Cannot GET /socket.io/
Request URL: http://localhost:4200/socket.io/?EIO=3&transport=polling&t=NVvJf99
Request Method: GET
Status Code: 404 Not Found
Remote Address: 127.0.0.1:4200
I can show the list who sent me friend but I need everytime to reload page to see new requests.
I am using socket.io in both frameworks.
Angular I have installed with npm and the same in the mongoDB.
My server.js that is what I use for the requests and responses in frontend.
Server.js
const express = require('express');
const mongoose = require('mongoose');
const http = require('http');
const cors = require('cors');
const routes = require('./src/app/routes/routes');
const path = require('path');
const socketIO = require('socket.io');
const app = express();
const server = http.Server(app);
mongoose.connect('mongodb+srv://vip:admin#test-name-sn4qu.mongodb.net/test?retryWrites=true&w=majority'
, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
});
app.use(cors());
const io = socketIO(server);
app.set(io);
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}));
app.use('/images', express.static(path.resolve(process.cwd(), '../images')));
app.use(routes);
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
app.get("/", (req, res) => {
res.json({ message: "Welcome to application." });
});
const PORT = process.env.PORT || 5000;
server.listen(PORT);
And then in the friendController I use something like this.
function createNewRequest(req, res, next) {
const io = req.app.get('io');
friendService.createNewRequest(req.body)
.then(res.status(200).json({ message: 'Friend added successfully' }),
io.emit('newTaskAdded'))
.catch(err => next(err));
}
And then in the frontend I do have something like this.
And I am having an error which says
Cannot find namespace 'SocketIOClient'. private socket:SocketIOClient.Socket;
import * as io from "socket.io-client";
constructor() {
this.socket = io();
}
ngOnInit(): void {
this.LoadRequestingFriends();
this.socket.on('newTaskAdded', () => {
this.LoadRequestingFriends();
})
}

Problems with Webhooks and Websockets on the same port

I have a server that receives webhooks, sends them to a client via websockets. Since I am listening for both on the same port, if webhooks work, websockets dont and vice versa. How would I go about solving this. Here is the code for the server
const express = require('express');
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.json())
app.post("/", (req, res) => {
console.log(req.body);
res.status(200);
res.send(req.body);
echo(req.body);
});
app.listen(3000, '0.0.0.0', () => console.log('Server is live at 3000'));
const WebSocket = require('ws');
const SocketServer = require('ws').Server;
const server = express().listen(3000);
const wss = new SocketServer({server});
wss.on('connection', (ws) =>{
console.log("Connected");
ws.send("Connected To Server")
ws.on('close', () => console.log("Disconnected"));
});
function echo(webhook){
wss.clients.forEach(function each(client){
client.send(webhook);
});
}
How would I run webhook listener and websocket sender/listener on same port
Can I run both of them on different ports on the same url
a) If yes what would be the url for both ports, if my website is www.example.com
If all that is not possible, what would be a good alternative

How to send ws message from route request

I've been trying to create an app that uses telegram-bot, express server and react app. Therefore, I need to create a POST request from telegram-bot to express, while express sends POST data to a websocket connection:
const express = require("express");
const app = express();
const expressWs = require("express-ws")(app);
// handles bot request
app.post("/request", (req, res) => {
playlist.push(req.body.url);
res.status(200).send({ message: "video is added to playlist" });
});
// after handling requst data must go here and send ws message to client side
app.ws("/echo", (ws, req) => {
ws.on("message", msg => {
ws.send(`msg is = ${msg}`);
});
});
Am I making it right, and if so, how to call ws.send from after handling request at app.post route?
From the understanding I have from your question, here is an updated version of your code that does exactly what you want.
I replaced the express-ws package with ws since that would be sufficient for your use case.
The express server runs on port 8080 while the websocket server runs on port 8081 since are different protocols and would not run on the same port (You can make it work but I do not recommend it See this question
const express = require("express");
const Websocket = require('ws');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const wss = new Websocket.Server({ port: 8081 });
wss.on('connection', (ws) => {
console.log('One client connected');
ws.on("message", msg => {
ws.send(`msg is = ${msg}`);
});
})
// handles bot request
app.post("/request", (req, res) => {
// Broadcast URL to connected ws clients
wss.clients.forEach((client) => {
// Check that connect are open and still alive to avoid socket error
if (client.readyState === Websocket.OPEN) {
client.send(url);
}
});
res.status(200).send({ message: "video is added to playlist" });
});
app.listen(8080, () => {
console.log('Express listening on 8080');
console.log('Websocket on 8081');
});
Tested via curl with curl -d 'url=https://example.com/examplesong' localhost:8080/request I had a client connected to ws://localhost:8081 and everything looks good.

WebSocket connection closes when server sends message only on port 80

I have a simple, local Nodejs server running Express. I'm using express-ws to set up a WebSocket endpoint. The client sends messages fine, and the server receives them, but when the server tries to send a message back, the connection closes and the client never receives the message.
This only happens over port 80. The connection stays open over port 3000, 8080, 443, and the client receives the messages the server sends back.
app.js
const express = require('express');
const path = require('path');
const app = express();
const expressWs = require('express-ws')(app);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res, next){
res.send(`<script src="js/client.js"></script>`);
});
app.ws('/', function(ws, req) {
ws.on('message', function(msg) {
console.log(msg);
ws.send(msg); //The connection doesn't close with this commented out
});
});
app.listen(80);
client.js
const ws = new WebSocket(`ws://${window.location.host}`);
ws.onopen = function(e){
console.log("WebSocket connected");
ws.send("testing 1");
ws.send("testing 2");
}
ws.onmessage = function(msg){
console.log(msg);
}
I'm at a loss. Any help would be appreciated.

Categories