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.
Related
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.
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
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
My socket.connected is always false, cannot emit or receive messages too.
app.js
var app = require('./config/server');
var http = require('http').Server(app);
var io = require("socket.io")(http);
http.listen(80, function(err)
{
console.log(err);
console.log('Server client instagram_clone_v01 online');
});
io.sockets.on('connection', function (socket)
{
console.log("new user connected");
});
server side
var sockets = io();
sockets.on('connection', function ()
{
console.log("connected");
sockets.emit("newPhoto");
});
client side
const socket = io.connect("http://localhost:80");
console.log(socket.connected);
socket.on('error', function()
{
console.log("Sorry, there seems to be an issue with the connection!");
});
socket.on('connect_error', function(err)
{
console.log("connect failed"+err);
});
socket.on('connection', function ()
{
console.log("connected");
socket.on('newPhoto',function()
{
load_posts();
});
});
None of the "on"s are received, not even "error". So how can i make it work, please?
I've checked Your code locally.
So issue was that You're checking: .on('connection',...) when it should be .on('connect', ...)
So try this fix:
socket.on('connect', function() {
console.log("Connected to WS server");
console.log(socket.connected);
load_posts();
});
socket.on('newPhoto', function(){
load_posts();
});
When I was building a basic socketio app using React frontend and Node Express backend, I came across a similar problem in v4. With the typical Node/React setup, your react app will live on port 3000 and your express server will live on port 5000, and according to the docs this results in you needing to set an open CORS policy to enable connections to the socketio server on port 5000.
Since Socket.IO v3, you need to explicitly enable Cross-Origin
Resource Sharing (CORS).
(docs)
I simply made sure my socketio definition was as such:
const app = express();
const httpServer = http.createServer(app);
const io = require("socket.io")(httpServer, {
cors: {
origin: "http://localhost:8080",
methods: ["GET", "POST"]
}
});
and I Was able to connect from a my react app inside of a useEffect. I was seeing all of the expected logs thereafter.
useEffect(() => {
socket = io('localhost:5000');
socket.on('connect', () => {
console.log('socket connected');
console.log(socket);
});
}, []);
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.