I have a button on a page that when it is clicked, i want the page to call some node.js server code. I have this wired up via socket.io. The issue I am running into is I need the socket.io code to redirect my web page based on some business logic. Not sure what is the best way to do that via express (res.redirect?) and also how to get access to that within the socket.io call. Any help would be appreciated!
App.js
var dashboard = require('./middleware/dashboard.js');
...
app.get("/dashboard", function (req, res) {
dashboard.show(req, res);
});
...
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
io.set('log level',2); // sets socket io log level 0=error, 1=warn, 2=info, 3=debug
...
dashboard.wireUpSocketIO(io);
...
dashboard.js
var savedResponse;
exports.show = function(req, res) {
savedResponse = res;
res.render("dashboard.jade"});
};
exports.wireUpSocketIO = function(io){
io.sockets.on('connection', function (socket) {
socket.on('dashboardOnButtonClick', function(msg) {
<biz logic>
savedResponse.render("someOtherPage.jade", {
locals: {
title: "someOtherPage",
filter: msg.filter
}
});
});
});
}
dashboard.jade
button#btnFilter(class='btn btn-info') Test Button
script(src="/socket.io/socket.io.js")
script .
var socket = io.connect('http://localhost');
var emitMessage = { blah: false, filter:"n/a"};
$('#btnFilter').click(function(){
emitMessage.blah = true;
emitMessage.filter = "filterByBlah";
socket.emit('dashboardOnButtonClick', emitMessage);
});
I could think it is easier to do from the client side, that is, javascript:
Once the server side logic is done, you send a message back to the client and change the window.location to the new one.
Once the server is done, the client can issue a request to that the server will respond with a HTTP 301/302 Redirect. This way you can call res.Redirect on that Express request.
Regards,
Related
I just set up SocketIO in my PHP project. I am completly new to websockets at all so bear with me.
I am defining the socketIO variable globally
let socketIO = io("http://localhost:3000");
When people are logging in to my application, they are connected to it with their ID comming from the database. The login script just gives back true which redirects the user in very simplified terms:
// get component
$.get(url, data, (data) => {
if (data.status) {
// connect with Node JS server
socketIO.emit("connected", data.user_id);
// redirect
load_new_page("/users/" + data.user_id);
}
});
My concern here now is that people could just go and change the data.user_id to anything they want and receive what ever the chosen id would receive.
My server.js:
// initialize express server
var express = require("express");
var app = express();
// create http server from express instance
var http = require("http").createServer(app);
// include socket IO
var socketIO = require("socket.io")(http, {
cors: {
origin: ["http://localhost"],
},
});
// start the HTTP server at port 3000
http.listen(process.env.PORT || 3000, function () {
console.log("Server started running...");
// an array to save all connected users IDs
var users = [];
// called when the io() is called from client
socketIO.on("connection", function (socket) {
// called manually from client to connect the user with server
socket.on("connected", function (id) {
users[id] = socket.id;
});
});
});
How can I prevent something like this?
I'm creating a web application which has two web portals, and a node server. First portal sends HTTP requests(POST) while the second web portal should show them. Then a user will type some text and send it back to the server through the socket and it should redirect it to the first portal. I've used socket.io for the communication happen between the second portal and the server, while the first one does it though post. I'm struggling with finding a way to receive the answer from the second web portal and send the answer back to the first one. Here's the code.
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(5700);
io.on('connection', function (socket) {
console.log("connected" + socket.id);
});
app.post('/server', rawBody, function(req, res, next){
var question = req.query.question;
io.emit('question', {data: question});
io.on('answer', function(data) {
var body = {
response: "data.answer"
};
res.json(body);
});
});
As I've found io.on('answer', function(data) is incorrect. But what I need is something like this:
io.on('answer', function(data) {
var body = {
response: "data.answer"
};
res.json(body);
});
Could you please tell me how should I get the answer back from the socket and upon receive it, send the reply back to the first web portal.
Something like this:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(5700);
io.on('connection', function (socket) {
console.log("connected" + socket.id);
app.post('/server', rawBody, function(req, res, next){
var question = req.query.question;
socket.emit('question', {data: question});
});
socket.on('answer', function(data) {
var body = {
response: "data.answer"
};
res.json(body);
});
});
I have fetched a copy of the latest Mean.io and noted quite a number of changes compared to the previous version I have been working with before. Now, what I am doing is creating a very basic chat application that uses socket.io with rooms. Following the basic setup in the Socket documentation I have to implement the following:
var app = require('express')()
, server = require('http').createServer(app)
, io = require('socket.io').listen(server);
server.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Where would I define the basic socket room setup?
socket.set("log level", 1);
var people = {};
var rooms = {};
var clients = [];
You can set the socket.io to listen on your server on
/server/config/system/bootstrap.js
Require the socket.io module
var express = require('express'),
appPath = process.cwd(),
io = require('socket.io');
Now set the socket.io to listen on your app
// Express settings
var app = express();
require(appPath + '/server/config/express')(app, passport, db);
io = io(app.listen(3000));
return io;
Then you need to inject the socket.io object into your app on bootstrapDependencies() function.
function bootstrapDependencies() {
...
// Register socket.io dependency
mean.register('io', function() {
return io;
});
}
Mean.uses this project for its dependency injection
https://www.npmjs.org/package/dependable
Finally you need to configure your app to listen on every socket connections
probably you want to do these on your main app's router at
/server/routes/index.js
Sample connection handler
var io = require('meanio').io;
io.on('connection', function (socket) {
// emit data to the clients
socket.emit('news', { hello: 'world' });
// event listeners
socket.on('my other event', function (data) {
// call your controller function here
Controller.action(data);
});
});
And more importantly, don't forget to setup socket.io on the client side.
// on '/server/views/includes/foot.html'
<script src='/socket.io/socket.io.js'></script>
<script>
var socket = io();
</script>
I've just responded to another SO post (Mean.io framwork with socket.io).
Note: I'm using mean.io v0.5.26 and socket.io v1.1.0.
Pasting my answer again, here.
I also faced the same issue and took me about a week to finally get it right. I'll try to explain what I did:
app.js
In this file, I just invoke the code that creates and sets up a socket.io object for me, which is then passed to the routes module.
'use strict';
/*
* Defining the Package
*/
var Module = require('meanio').Module;
var MeanSocket = new Module('chat');
/*
* All MEAN packages require registration
* Dependency injection is used to define required modules
*/
MeanSocket.register(function(app, http) {
var io = require('./server/config/socketio')(http);
//We enable routing. By default the Package Object is passed to the routes
MeanSocket.routes(io);
return MeanSocket;
});
server/config/socketio.js
This file simply configures the socket.io object. Please note that I had to upgrade meanio module to version 0.5.26 for this work, as http object (express server) is not available in older meanio versions. Moreover, in case you want to use ssl, you can inject https instead of http.
'use strict';
var config = require('meanio').loadConfig(),
cookie = require('cookie'),
cookieParser = require('cookie-parser'),
socketio = require('socket.io');
module.exports = function(http) {
var io = socketio.listen(http);
io.use(function(socket, next) {
var data = socket.request;
if (!data.headers.cookie) {
return next(new Error('No cookie transmitted.'));
}
var parsedCookie = cookie.parse(data.headers.cookie);
var sessionID = parsedCookie[config.sessionName];
var parsedSessionID = cookieParser.signedCookie(parsedCookie[config.sessionName], config.sessionSecret);
if (sessionID === parsedSessionID) {
return next(new Error('Cookie is invalid.'));
}
next();
});
return io;
};
routes/chat.js
Finally, use the routes file to define the socket events, etc.
'use strict';
// The Package is passed automatically as first parameter
module.exports = function(MeanSocket, io) {
io.on('connection', function(socket) {
console.log('Client Connected');
socket.on('authenticate', function(data, callback) {
});
});
};
Hope this helps!
The latest update v0.4.0 requires another strategy to get socket.io setup. I'm currently in discussion with one of the project contributors to validate my solution. I'll make sure to update my response once I'm 100% sure.
The meanio package is now where the bootstrap functionality is located, as well, where express setup is being called from.
Looks like the mean.io guys have recently released an official Socket.io implementation that integrates directly with their stack. Check it out on Github.
I am working on realtime data visualization application using node.js, express and socket.io.
Requirement:
Have to emit the events based on the client request.
For example: If user enter the url as http://localhost:8080/pages socket.io should emit the topic pages to client and another user request for http://localhost:8080/locations socket should emit location to that particular user.
Code
var server = app.listen("8080");
var socket = require('socket.io');
var io = socket.listen(server);
var config = {};
io.on('connection', function (socket) {
config.socket = io.sockets.socket(socket.id);
socket.on('disconnect', function () {
console.log('socket.io is disconnected');
});
});
app.get('/*', function(req, res) {
var url = req.url;
var eventName = url.substring('/'.length);
//pages and locations
config.socket.volatile.emit(eventName, result);
});
Client Code:
//No problem in client code.Its working correctly.
Sample code as follows
socket.on('pages', function (result) {
console.log(result);
});
Problem:
It is emitting pages and locations to both the clients.
Any suggestion to overcome this problem.
I couldn't understand your approach on this, but because you said you're rendering different pages, It means you can serve different code, so what about doing it like this:
Server Side:
var server = app.listen("8080");
var socket = require('socket.io');
var io = socket.listen(server);
var config = {};
app.get('/pages', function(req, res) {
res.render('pages.html');
});
app.get('/locations', function(req, res) {
res.render('locations.html');
});
io.on('connection', function (socket) {
socket.on('pagesEvent', function(data){
socket.volatile.emit('pages', {your: 'data'});
});
socket.on('locationsEvent', function(data){
socket.volatile.emit('locations', {your: 'data'});
});
});
On Client side:
pages.html:
socket.on('connect', function(){
socket.emit('pagesEvent', {});
});
socket.on('pages', function(data){
// do stuff here
});
locations.html:
socket.on('connect', function(){
socket.emit('locationsEvent', {});
});
socket.on('locations', function(data){
// do stuff here
});
You are doing it wrong, WebSockets supposed to work same in both directions. Client emit event to Server, server emit back to Client/Subscribers.
The way you are doing things, seems like a way of implementing API, but for some reason you are trying to implement it with WebSockets, instead of XHR.
I'm trying to check the username in the NodeJs chat with the user session. Is there a secure way to do it? (My NodeJs server isn't in the same place as the host of the website). I'm using this code NodeJs + express to do the chat application.
Code:
var express = require('express');
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server, { log: false });
server.listen(8080);
app.get('/chat.js', function(req, res) {
res.sendfile('chat.js');
});
/* CHAT FUNCTIONS */
io.sockets.on('connection', function (socket) {
socket.on('send', function (data) {
// I wanna get the user session
// something like this:
// (code below does not exist)
var username = session['username'];
console.log(username + " is here.");
io.sockets.emit('message', data);
});
});
How can I do this?
You need to use common storage for sessions e.g. memcached or redis.
Than u will have common access.