I have the app.js code:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('newRideAdded', function(exclude){
io.emit('newRideAdded', exclude);
});
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(express.static(__dirname + '/public/'));
app.use('/rides', require('./routes/rides'));
app.use('/user', require('./routes/user'));
server.listen("8080", function() {
console.log("Connected to db and listening on port 8080");
});
And I want to move the socket io code to its router's page.
That is the router page:
var express = require('express');
var router = express.Router();
var mongojs = require('mongojs');
var db = mongojs("ride4you", []);
router.post('/getRides', function(req, res, next) {
db.rides.find(function(err, docs) {
res.json(docs);
});
});
// rest of the restapi in this page.
// I want socket code to be here
module.exports = router;
As you can see i have each socket emits in each router's page and I already have module.exports in routers page.
How can it be done?
Thanks.
Using Express 4, in your app.js file you can use
app.set('socketio', io);
Then in your router or controller, you can use
router.post('/getRides', function(req, res, next) {
var io = req.app.get('socketio');
io.to(//socket.id//).emit("message", data);
db.rides.find(function(err, docs) {
res.json(docs);
});
};
This is a clean way of passing the reference along.
Related
i'm little stuck on my express application.
I have a file index.js in routes folder and I want to save the result of mydata
var express = require('express');
var router = express.Router();
router.get('/', token, function(req, res, next) {
var mydata = req.userId
res.render('index', {
title: 'Welcolme',
});
});
module.exports = router;
And, in my other file (which depends on app.js), I would like to get and pass mydata to the server
var app = require('../app');
server.listen(port, function () {
require('../assets/js/server/socket')(server, mydata);
});
(Here is my app.js)
var express = require('express');
var indexRouter = require('./routes/index');
var path = require('path');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'twig');
app.use('/', indexRouter);
module.exports = app;
And the socket file
var io = {};
module.exports = (server, mydata) => {
console.log('Hello : ' , mydata)
io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('Connected')
});
};
Is there a way to do that?
Thank you :)
Maybe instead of still having this route.get('/') ...
You can let the user enter the data and have it transferred directly through the WebSocket connection.
Example:
//Client-side
//Get the user data somewhere from the HTML page
const userData = document.getElementbyId("some html element's id here").innerHTML;
//Send it to the back end
socket.emit('userData',userData)
//Open a listener to get the data from the back end later
socket.on('processedData',processedData=>{
//Use it in the way you desired.
});
//Server-side
io.on('connection', (socket) => {
console.log('Connected')
socket.on('userData',userData=>{
//Do something here, like validation and stuff
socket.emit('processedData','processedData here')
});
});
In one of my node.js script i am trying to use socket.io in express route. I found many similar questions and tried to implement the solution as suggested but nothing worked out. May be because of my lack of understanding of express routes. I followed below links,
How use socket.io in express routes with node.js
Use socket.io in expressjs routes instead of in main server.js file
This is my app.js
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');
//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});
app.get('/', (req, res) => {
res.send("this is home location");
});
And route file api.js in ./routes folder
var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
console.log("inside api route");
router.get('/', function(req, res, next) {
console.log("api route called");
const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
io.sockets.on('connection',(socket) => {
connections.push(socket);
console.log(' %s sockets is connected', connections.length); // this is not printing
socket.on('disconnect', () => {
connections.splice(connections.indexOf(socket), 1);
});
socket.emit('server message', jsonobj);
});
//res.send(jsonobj)
});
module.exports = router;
Socket.emit is not showing data on html page i am rendering on route use. My html code is,
//api.html
<!DOCTYPE html>
<html lang="en">
<body>
<div class="container">
<h1 class="jumbotron">
Node js Socket io with socket route example
</h1>
<div class="results">results</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script>
jQuery(document).ready(function() {
var socket = io.connect();
var jsondata = "";
socket.on('server message', function(data){
console.log('got data from server',data)
jsondata = JSON.stringify(data);
//console.log('jsondata',jsondata)
$('.results').html(jsondata);
});
});
</script>
</body>
</html>
Please suggest what i am supposed to get route socket data in html page.
Thanks
Ok, let's try to understand why do you need to send data via the socket inside a route in the first place. Websockets are meant for sending data asynchronously without the client having to make a request. If the client is already making an HTTP request, then you can just send the data in the HTTP response.
Now having said there, there are clearly some use cases where you have to send data to some WebSocket channel based on the actions of some OTHER user's requests. If that is the case, there are multiple ways of doing this. One clean way would be to use an event-driven architecture.
Try something like this... find my comments inline below -
const express = require('express');
const router = express.Router();
const fs = require("fs");
const bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
// move the socket connection outside of the route controller
// you must register the event listeners before anything else
const connections = [];
io.sockets.on('connection', (socket) => {
connections.push(socket);
console.log(' %s sockets is connected', connections.length); // this is not printing
socket.on('disconnect', () => {
connections.splice(connections.indexOf(socket), 1);
});
});
// Event emitter for sending and receving custom events
const EventEmitter = require('events').EventEmitter;
const myEmitter = new EventEmitter();
myEmitter.on('my-event', function (jsonobj) {
// do something here like broadcasting data to everyone
// or you can check the connection with some logic and
// only send to relevant user
connections.forEach(function(socket) {
socket.emit('server message', jsonobj);
});
});
router.get('/some-route', function (req, res, next) {
const jsonobj = [{ name: "john", score: 345 }, { name: "paul", score: 678 }]
// emit your custom event with custom data
myEmitter.emit('my-event', jsonobj);
// send the response to avoid connection timeout
res.send({ok: true});
});
module.exports = router;
At first glance, it looks like you are delcaring the URL prefix twice. Once in app.js and again in api.js.
Try localhost:port/api/api
If this is the case, change
router.get('/api', function(req, res, next){
to
router.get('/', function(req, res, next){
This will allow you to hit localhost:port/api and access your endpoint.
I am just starting to understand this myself, but I think where you are at is close.
In your app.js add to the end of the file:
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');
//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});
app.get('/', (req, res) => {
res.send("this is home location");
});
app.set("socketio", io); // <== this line
That stores the "io" variable in "socketio". Which you can grab in any of your other ".js" files.
var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
//const io = require('socket.io').listen(server); // <== change this
const io = app.get("socketio"); // <== to this
console.log("inside api route");
router.get('/', function(req, res, next) {
console.log("api route called");
const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
io.sockets.on('connection',(socket) => {
connections.push(socket);
console.log(' %s sockets is connected', connections.length); // this is not printing
socket.on('disconnect', () => {
connections.splice(connections.indexOf(socket), 1);
});
socket.emit('server message', jsonobj);
});
//res.send(jsonobj)
});
module.exports = router;
And you should do that with any other variables which are required in other ".js" files.
Also note that in your files, you are setting the variables up again. It is better to do the same as I've shown you with "io". The only variable in other files I setup is "app" itself.
Hope this helps...
You tried to create and start the servers from two different places in your single project, which is inconvenient. You just need some cleanup, that's all.
app.js
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);
// Listen to sockets here instead of listening in routes/api.js
const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
io.sockets.on('connection',(socket) => {
connections.push(socket);
console.log(' %s sockets is connected', connections.length); // this is not printing
socket.on('disconnect', () => {
connections.splice(connections.indexOf(socket), 1);
});
socket.emit('server message', jsonobj);
});
const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');
//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});
app.get('/', (req, res) => {
res.send("this is home location");
});
routes/api.js
var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');
// Comment these out
// const app = express();
// const server = require('http').createServer(app);
// const io = require('socket.io').listen(server);
console.log("inside api route");
router.get('/', function(req, res, next) {
console.log("api route called");
// Comment these out
// const connections = [];
// var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
// io.sockets.on('connection',(socket) => {
// connections.push(socket);
// console.log(' %s sockets is connected', connections.length); // this is not printing
// socket.on('disconnect', () => {
// connections.splice(connections.indexOf(socket), 1);
// });
// socket.emit('server message', jsonobj);
// });
//res.send(jsonobj)
});
module.exports = router;
Leave your api.html as it is. Hope this helps.
I have two EC2 instances, and I am using socket.io to establish communication between them.
In my First Server I have the following files
server1.js
........
........
var loadData = require("./client/getData");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', loadData);
var port = Number(process.env.PORT || 5000);
app.listen(port);
var server = require("https").Server(app);
var io = require("socket.io-client");
app.set('socketio', io);
..........
getData.js
......
router.get('/getMetaData', function(req, res){
var io = req.app.get('socketio');
var socket = io.connect('https://172.43.3.2:8080');
socket.on('metaData', function(data){
console.log("MetaData:", data);
res.json(data);
});
});
module.exports = router;
In my Second Server i have the following
server2.js
var express = require('express');
var app = express();
var server = require("https").Server(app);
var io = require("socket.io")(server);
app.get('/', function (req, res) {
res.send('Hello World');
});
var port = Number(process.env.PORT || 5000);
app.listen(port);
var metaData = {
"block1":["id1","id2"]
}
io.on('connection', function(socket){
console.log("Received Connection");
socket.emit('metaData', metaData);
});
console.log("Server Running on:", process.env.PORT);
My request to the route /getMetaData is resulting in "504 Gateway Time-out", I am not sure what I am doing wrong or missing out on
I am working on app which uses node, express, mysql on server side. i have written serveral APIs on server.js file and when i am trying to access those using Postman then req.body is always undefined.
this is my server.js configuration.
var express = require('express');
var mysql = require('mysql');
var cors = require('cors');
var bodyParser = require('body-parser');
var wrench = require("wrench");
var fs = require('fs');
var path = require("path");
var mkdirp = require('mkdirp');
var walk = require('walk');
var fse = require('fs-extra');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
var crypto = require('crypto');
app.use(cors());
app.use(bodyParser.urlencoded({limit: '50mb',extended: false}));
app.use(bodyParser.json({limit: '50mb'}));
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'pass',
database: 'dbname'
});
connection.connect(function(err) {
if (!err) {
console.log("Database is connected ... \n\n");
} else {
console.log("Error connecting database ... \n\n");
}
});
app.post('/urlreq', function(req, res){
console.log(req.body);
}
app.listen(3000, function(){
console.log("Rest Demo Listening on port 3000");
});
When i am trying send something in body in Postman then req.body is coming empty on server side.
If you are sending multipart/form-data, it doesn't work because bodyparser doesn't handle this body type.
In this case adding the following line should fix it:
app.use(multipartMiddleware);
Form the docs:
multipart/form-data is the default encoding a web form uses to transfer data
Try add:
var express = require('express');
var app = express();
[...]
// Last stack
app.listen(3000, function(){
console.log("Rest Demo Listening on port 3000");
});
You can use as a middleware also. Also listen on a port. add following lines in your code -
var app = express();
app.use(function(req, res, next) {
console.log('Current User:', req.body);
next();
});
app.post('/url', function(req,res){
console.log(req.body)
});
app.listen(3000, function(){
console.log('Express server listening on port 3000');
});
I have created a new Express application. It generated app.js for me and I have then created the following index.js bringing in socket.io:
var app = require('./app');
server=app.listen(3000);
var io = require('socket.io');
var socket = io.listen(server, { log: false });
socket.on('connection', function (client){
console.log('socket connected!');
});
Can anyone advise how I would access socket.io within the routes files?
For reference, the default generated app.js is below:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
/// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
SocketIO does not work with routes it works with sockets.
That said you might want to use express-io instead as this specially made for this or if you are building a realtime web app then try using sailsjs which already has socketIO integrated to it.
Do this to your main app.js
app = require('express.io')()
app.http().io()
app.listen(7076)
Then on your routes do something like:
app.get('/', function(req, res) {
// Do normal req and res here
// Forward to realtime route
req.io.route('hello')
})
// This realtime route will handle the realtime request
app.io.route('hello', function(req) {
req.io.broadcast('hello visitor');
})
See the express-io documentation here.
Or you can do this if you really want to stick with express + socketio
On your app.js
server = http.createServer(app)
io = require('socket.io').listen(server)
require('.sockets')(io);
Then create a file sockets.js
module.exports = function(io) {
io.sockets.on('connection', function (socket) {
socket.on('captain', function(data) {
console.log(data);
socket.emit('Hello');
});
});
};
You can then call that to your routes/controllers.
The route:
const Router = require('express').Router
const router = new Router();
router.get('/my-route', (req, res, next) => {
console.log(req.app.locals.io) //io object
const io = req.app.locals.io
io.emit('my event', { my: 'data' }) //emit to everyone
res.send("OK")
});
module.exports = router
The main file:
const app = require('express')()
const server = require('http').Server(app);
const io = require('socket.io')(server)
const myroute = require("./route") //route file dir
app.use(myroute);
server.listen(3000, () => {
console.log('¡Usando el puerto 3000!');
});
app.locals.io = io
I think a better way to do it is to attach the Io server to response object In the first middleware .per the way express is designed the Io server will be available to your subsequent routes.
Check this link