How to use socket.io with express-session that coming from controller - javascript

In my app.js ı using route in middleware like this:
app.use('/myPage', pageRoute);
my route page:
router.get('/new', pageController.pageFunc);
and my controller:
exports.pageFunc = (req, res, next) => {
res.render('myPage/pugFile', {
name: req.session.userName
});
}
Its working perfectly but i want use this session with my socket in my app.js
my socket is like this:
io.on('connection', socket => {
socket.on('myIo', (par) => {
console.log(par);
});
});
if i try to use req.session.userName in my socket i taking req is not defined error. How can i use my sessions in this socket?

i solved my problem with middleware like this:
app.use('/myPage', pageRoute);
let mySession;
app.use((req,res,next)=>{
mySession = req.session.userName;
next();
});
io.on('connection', socket => {
socket.on('myIo', () => {
console.log(mySession );
});
});
EDIT: There are some problems in this solution , because mySession value changing with other user connection but finally i found solution.
You can use socket.request.session they explain how you can use in there: Usage with express-session

Related

Whats the best way save a users last route location using express.js

Consider a simple serverside node app.
const router = express.Router();
router.get("/path1",function(req,res) {
...
});
router.get("/path2",function(req,res) {
...
});
What's a great way to save the user's last location using localStorage or Cookies or anything? i.e.) www.somewebpage.com/path1 or www.somewebpage.com/path2
I was hoping for something like
router. <forAllPaths>(o => {
localStorage.setItem(<...set url code>);
})
I would recommend that you use redis and in each route you generate a middleware that stores or updates the last route used
const redis = require("redis");
const client = redis.createClient();
const middleware = async (res, req, next) => {
client.set(userId, req.originalUrl);
next()
}
client.on("error", error => {
console.error(error);
});
const router = express.Router();
router.get("/path1", middleware, async (req,res) => {
});
router.get("/path2", middleware, async (req,res) => {
});

How to modularize an express app - with a function, a class and req.pipe?

Here below there are two servers and two gqlServers. All combinations of them work.
The challenge is to extend express with some additional predefined code patterns shared across several apps, exposed through additional methods.
Which combination of a server and gqlServer is considered best practice and best for performance?
server:
server_A is a function that returns a class
server_B is a function that returns a function
gqlServer:
gqlServer_01 uses req.pipe
gqlServer_02 has the original express() passed into it
function gqlServer_01(options) {
let gqlApp = express();
gqlApp.use(options.route, function(req, res, next) {
res.send('gqlServer 01');
// next();
});
gqlApp.listen(8001, err => {
if (err) throw err;
console.log(`>> GQL Server running on 8001`);
});
}
function gqlServer_02(app, options) {
app.use(options.route, function(req, res, next) {
res.send('gqlServer 02');
// next();
});
}
// THIS SERVER ?
function server_A(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
class Server {
constructor(opt) {
this.opt = opt;
}
gql(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
}
}
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return new Server(app, config);
}
// OR THIS SERVER ?
function server_B(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
app.gql = function(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
};
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return app;
}
The goal is to have the best solution in order to create an npm package out of this and reuse the methods over several projects easily. The project was highly simplified for the sake of clarity.
I don't think you will have performance issues in any of these examples, so the question remains which of them is more modular.
If you are willing to make an npm package out of these, you shouldn't be calling express() inside your server code. Instead you should be passing the app as a parameter. This will allow you to reuse existing express apps initialized elsewhere. For this reason I would go for gqlServer_02
You also want to create a new server each time you call the module function, so I'd go with server_A for this reason. However it needs to receive the express app as parameter, in order to reuse existing express objects. I would also put the app.listen call inside a function in the Server class.

Cannot GET / DELETE Express.js

I have this script with which I'm trying to POST, GET and DELETE some stuff.
When I try POST or GET, the right messages are logged, but when I try DELETE, I get the following error:
Cannot GET /del_user
The URL I'm using is http://127.0.0.1:8081/del_user
What can be wrong in here?
var express = require('express');
var app = express();
// This responds with "Hello World" on the homepage
app.get('/', function (req, res) {
console.log("Got a GET request for the homepage");
res.send('Hello GET');
})
// This responds a POST request for the homepage
app.post('/', function (req, res) {
console.log("Got a POST request for the homepage");
res.send('Hello POST');
})
// This responds a DELETE request for the /del_user page.
app.delete('/del_user', function (req, res) {
console.log("Got a DELETE request for /del_user");
res.send('Hello DELETE');
})
// This responds a GET request for the /list_user page.
app.get('/list_user', function (req, res) {
console.log("Got a GET request for /list_user");
res.send('Page Listing');
})
// This responds a GET request for abcd, abxcd, ab123cd, and so on
app.get('/ab*cd', function(req, res) {
console.log("Got a GET request for /ab*cd");
res.send('Page Pattern Match');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
I solved it by changing the app.delete to app.get and then placing the required remove statement inside the app.get. Something like this :-
app.get('/delete/:userId', (req, res) => {
Users.remove({ _id: req.params.userId }, (error, posts) => {
if (error) {
console.warn(error);
}
else {
data = posts
res.render("delete", {"data": data})
}
});
});
In your code you're binding the /del_user URL to the HTTP DELETE method.
So all you need to do is specify the DELETE method in your application or in Postman.
If you're not using it, it's an App in Google Chrome and you might want to download it, it makes your life a LOT easier ;)
Also, since the HTTP method is already declared to be DELETE, there is no need to specify it in the URL.
This is part of the RESTful working.
If you are using AJAX to try your code, you need to specify the method, which is delete.
$.ajax({
url: "http://127.0.0.1:8081/del_user",
type: "DELETE"
});

Calling Express Route internally from inside NodeJS

I have an ExpressJS routing for my API and I want to call it from within NodeJS
var api = require('./routes/api')
app.use('/api', api);
and inside my ./routes/api.js file
var express = require('express');
var router = express.Router();
router.use('/update', require('./update'));
module.exports = router;
so if I want to call /api/update/something/:withParam from my front end its all find, but I need to call this from within another aspect of my NodeJS script without having to redefine the whole function again in 2nd location
I have tried using the HTTP module from inside but I just get a "ECONNREFUSED" error
http.get('/api/update/something/:withParam', function(res) {
console.log("Got response: " + res.statusCode);
res.resume();
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
I understand the idea behind Express is to create routes, but how do I internally call them
The 'usual' or 'correct' way to handle this would be to have the function you want to call broken out by itself, detached from any route definitions. Perhaps in its own module, but not necessarily. Then just call it wherever you need it. Like so:
function updateSomething(thing) {
return myDb.save(thing);
}
// elsewhere:
router.put('/api/update/something/:withParam', function(req, res) {
updateSomething(req.params.withParam)
.then(function() { res.send(200, 'ok'); });
});
// another place:
function someOtherFunction() {
// other code...
updateSomething(...);
// ..
}
This is an easy way to do an internal redirect in Express 4:
The function that magic can do is: app._router.handle()
Testing: We make a request to home "/" and redirect it to otherPath "/other/path"
var app = express()
function otherPath(req, res, next) {
return res.send('ok')
}
function home(req, res, next) {
req.url = '/other/path'
/* Uncomment the next line if you want to change the method */
// req.method = 'POST'
return app._router.handle(req, res, next)
}
app.get('/other/path', otherPath)
app.get('/', home)
I've made a dedicated middleware for this : uest.
Available within req it allows you to req.uest another route (from a given route).
It forwards original cookies to subsequent requests, and keeps req.session in sync across requests, for ex:
app.post('/login', async (req, res, next) => {
const {username, password} = req.body
const {body: session} = await req.uest({
method: 'POST',
url: '/api/sessions',
body: {username, password}
}).catch(next)
console.log(`Welcome back ${session.user.firstname}!`
res.redirect('/profile')
})
It supports Promise, await and error-first callback.
See the README for more details
Separate your app and server files with the app being imported into the server file.
In the place you want to call your app internally, you can import you app as well as 'request' from 'supertest'. Then you can write
request(app).post('/someroute').send({
id: 'ecf8d501-5abe-46a9-984e-e081ac925def',
etc....
});`
This is another way.
const app = require('express')()
const axios = require('axios')
const log = console.log
const PORT = 3000
const URL = 'http://localhost:' + PORT
const apiPath = (path) => URL + path
app.get('/a', (req, res) => {
res.json('yoy')
})
app.get('/b', async (req, res) => {
let a = await axios.get(apiPath('/a'))
res.json(a.data)
})
app.listen(PORT)

Nodejs accessing nested variable in global scope

How would I access socket in the global scope based on my following NodeJS code
io.on('connection', function (socket) {
console.log('connection '+socket)
socket.on("data",function(d){console.log('data from flash: ',d);});
socket.emit("message","wtfwtwftwftwf hello from server");
socket.on('disconnect', function (socket) {
console.log("disconnect");
});
});
I need to access socket from within the following app.post method
var express = require('express'),
multer = require('multer');
var app = express();
//auto save file to uploads folder
app.use(multer({ dest: './uploads/'}))
app.post('/', function (req, res) {
console.log(req.body); //contains the variables
console.log(req.files); //contains the file references
res.send('Thank you for uploading!');
});
app.listen(8080);
Haven't tested yet but going to try a simple getter function first
io.on('connection', function (socket) {
console.log('connection '+socket)
socket.on("data",function(d){console.log('data from flash: ',d);});
socket.emit("message","wtfwtwftwftwf hello from server");
return{
getSocket: function(){
return socket;
}
};
socket.on('disconnect', function (socket) {
console.log("disconnect");
});
});
io.getSocket() ??
Express's app and Socket.io have nothing to do with one another.
So fundamentally, you can't use socket inside app.post.
You need to identify the client. You can use Passport which has a Socket.io plugin that essentially bridges the app.post/get's req.user to socket.request.user.
Note: It doesn't have to be an authenticated client with user that's fetched from database, just a client with a temporary user stored in memory would do. Something like this:
app.use(function(req, res, next) {
if (!req.user) { // if a user doesn't exist, create one
var id = crypto.randomBytes(10).toString('hex');
var user = { id: id };
req.logIn(user);
res.redirect(req.lastpage || '/');
return;
}
next();
});
var Users = {};
passport.serialize(function(user) {
Users[user.id] = user;
done(null, user);
});
passport.deserialize(function(id) {
var user = Users[id];
done(null, user);
});
Then you can attach the client's socket ID to its user session.
io.on('connection', function (socket) {
socket.request.user.socketid = socket.id
});
And then instead of socket.emit use io.emit in app.post using the socketid
app.post('/', function (req, res) {
io.to(req.user.socketid).emit('whatever');
});
Note: io.to() is used to emit to a room, but every socket is by default joined to the same room named as its socket.id, so it'll work.
Javascript and socketIO experts > please tell me why this simple solution shouldn't work. It seems to...
1 Define a global pointer
var _this=this;
2 In my socketIO handler make a reference to the socket object
_this.socket=socket;
3 And finally within app.post, access the socket like thus
_this.socket.emit(....

Categories