Why app.use(...) can't be declared in an async function? - javascript

I'm trying to set up a node.js server using the express framework and implement sessions.
This works :
var express = require('express');
var session = require('express-session');
var redis = require('redis');
var server = express();
var redisClient = redis.createClient();
server.use(session({secret: 'mySuperSecretKey'}));
server.listen(8000, function () {
console.log('listening...');
});
server.get('/', function (req, res) {
req.session.aSessionEntry = 'value';
res.send('Your session entry is' + req.session.aSessionEntry);
});
However, when I declare the server.use(session(...)) inside an async function, it is ignored - the session handling doesn't work anymore.
Here :
var express = require('express');
var session = require('express-session');
var redis = require('redis');
var server = express();
var redisClient = redis.createClient();
redisClient.get("sessionSecret", function(err, reply) {
server.use(session({secret: reply.toString()}));
};
server.listen(8000, function () {
console.log('listening...');
});
server.get('/', function (req, res) {
req.session.aSessionEntry = 'value';
res.send('Your session entry is' + req.session.aSessionEntry);
});
Why isn't it possible to do this ?

Middleware must be installed before specific route handlers. If you look in the Express code for app.use() and app.get(), they both add handlers into the internal router stack and those handlers are search in the order they were added, regardless of whether they were middleware handlers or endpoint handlers. So, if you put your endpoint handlers first before the middleware handlers, then the middleware may not get called and certainly won't get called before the endpoint (thus likely defeating its purpose).
If you want to install your middleware async, then you need to install all the route handlers AFTER that async middleware is installed.

Related

express cant find route

i have a node.js back-end with express sever.
i have routes called templete.rpoutes.js:
const express = require("express");
const templateCtrl = require("../controllers/template.controller");
const router = express.Router();
router.route("/createtemplate").post(templateCtrl.createTemplate);
router.route("/uploadFinalTemplate").post(templateCtrl.uploadFinalTemplate);
// beneath are the routes with issue
router.route("/:templateId/productInfos").get(templateCtrl.productInfos);
router.route("/:templateId").get(templateCtrl.Read);
// router.param("templateId", templateCtrl.templateByID);
module.exports = router;
I have the defined method in template controller where i'm just logging stuff. no backend logic is there yet. so I expect when I make a call to these end point, i should get those logs displayed
I have configured express server as:
app.use("/api/template", templateRoute);
app.use("/api/productInfo", productInfoRoute);
app.use('/api/sendInformation', Notify)
// PORT
const port = process.env.PORT || 5000;
const server = app.listen(port, () => {
console.log("Connected to port " + port);
});
Note: the app is express.router() method and the controllers are required correctly and the other end-points work for the same controller.
so when I send a get request from postman to localhost:5000/api/template/5f870cd3b02fd77d0a576a54 I get a 404 and Not found in my console like this: (Plus the server is running)
as described in the documentation https://expressjs.com/en/guide/routing.html#express-router
const router = express.Router();
router.post("/createtemplate",templateCtrl.createTemplate);
router.post("/uploadFinalTemplate",templateCtrl.uploadFinalTemplate);
router.get("/:templateId/productInfos",templateCtrl.productInfos);
router.get("/:templateId",templateCtrl.Read);

What protocol should I use and what are the docs for it?

So I'm trying to build a Discord bot. These types of threads tend to get downvoted a lot on stackoverflow, so I'm hoping this doesn't happen to me.
This particular feature is acting as a temporary solution to my dashboard problem. Due to the nature of glitch.com's hosting, it's supposed to fall asleep after 5 minutes of http inactivity. I solved that already by adding a script that pings the URL every 4 minutes, but that caused another issue. I think what's happening is that because that script and the bot script are constantly running, and never technically 'finish', it never lets any incoming connection actually load the webpage. So my solution to that problem was to create another glitch project that would act as the dashboard website, and transfer information from the bot project. Of course then I'd need to create more scripts that communicate with each other via some internet protocol. The info recorded by the bot is all recorded in a private JSON database using the node-json-db npm library.
My problem is: I don't know what protocol would be best for this kind of thing. Even if I did know, then I'd have to go digging through the docs for the info I'm looking for.
My question is: What protocol should I use, and what docs do I need to read for this?
I've included some snippets of the code here:
The bot's server code (where I would add the script for communicating with the dashboard):
// server.js
// where your node app starts
// init project
const express = require('express');
const app = express();
const JsonDB = require('node-json-db');
const db = new JsonDB("myDataBase", true, true);
// we've started you off with Express,
// but feel free to use whatever libs or frameworks you'd like through `package.json`.
// http://expressjs.com/en/starter/static-files.html
app.use(express.static('public'));
// http://expressjs.com/en/starter/basic-routing.html
app.get('/', function(request, response) {
response.sendFile(__dirname + '/views/index.html');
});
app.post('/login/c3RvcCBoYWNrZXIh', function(request, response) {
var servername = request.param('servername');
var password = request.param('password');
if (db.getData("/" + servername + "/password") === password) {
response.json(db.getData("/" + servername));
} else {
response.json(null);
}
});
// listen for requests :)
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
// to keep the bot alive, since glitch puts projects to sleep after 5 mins of inactivity.
const http = require('http');
setInterval(() => {
http.get(`http://${process.env.PROJECT_DOMAIN}.glitch.me/`);
}, 270000);
The server.js on the dashboard website:
// server.js
// where your node app starts
// init project
const express = require('express');
const app = express();
const request = require('request');
// we've started you off with Express,
// but feel free to use whatever libs or frameworks you'd like through `package.json`.
// http://expressjs.com/en/starter/static-files.html
app.use(express.static('public'));
// http://expressjs.com/en/starter/basic-routing.html
app.get('/', function(request, response) {
response.sendFile(__dirname + '/views/index.html');
});
app.post('/login', function(request, response) {
var servername = request.param('servername');
var password = request.param('password');
if ("thereisnopassword" === password) {
response.sendFile(__dirname + '/dashboard/index.html');
} else {
response.sendFile(__dirname + '/views/wronginfo.html');
}
});
// listen for requests :)
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
I had this too, but solved it by simply putting the code to start the express server before the http loop.
// Require packages
const http = require('http');
const express = require('express');
const app = express();
// Express
app.get("/", (request, response) => {
response.sendStatus(200);
});
app.listen(process.env.PORT);
// Interval
setInterval(() => {
http.get(`http://${process.env.PROJECT_DOMAIN}.glitch.me/`);
}, 240000);
// Bot code
const Discord = require('discord.js');
const client = new Discord.Client();

Make a cookie when a user connects with socket. io - node js

have a server that uses socket.io. When a user connects it will assign them the user id thats made on the server then increment it by 1 so the next user with have a different id.
I want to use cookies for this, to check if they have previously logged in, if so, use that id, if not, use the one on the server.
the way to create a cookie is by using
res.cookie('cookie', 'monster')
but im not where i would put it, i tried putting it in the connect function but res wouldnt exist. and if i put it outside the function, how would i call it? Here is my code. This is the start of my server:
//Require npm modules
var express = require('express');
var http = require('http');
var events = require('events');
var io = require('socket.io');
var ejs = require('ejs');
var app = express();
//Set the default user Id to 1 and the default username to Guest
exports.Server = Server = function()
{
this.userId = 1;
this.userName = "Guest";
};
app.set('view engine', 'ejs');
app.get('/game/:id', function (req, res)
{
res.render('game', {game: req.params.id});
});
Server.prototype.initialise = function(port)
{
//Create the server using the express module
this.server = http.createServer(app);
//Declare the 'public' folder and its contents public
app.use(express.static('public'));
//Listen to any incoming connections on the declared port and start using websockets
this.server.listen(port);
this.startSockets();
this.em = new events();
consoleLog('SERVER', 'Running on port: ' + port);
};
Server.prototype.startSockets = function()
{
//When a user connects to the server on the 'game' socket
this.socket = io.listen(this.server);
this.socket.of('game').on('connection', function(user)
{
res.cookie('cookie', 'monster')
//Set their usedId and username
user.userId = this.userId;
user.userName = this.userName + " " + this.userId;
//Increment the user id by 1 so each user with get a unique id
this.userId++;
//Send a response back to the client with the assigned username and user id and initialise them
user.emit('connected', user.userId, user.userName);
this.em.emit('initialiseUser', user.userId, user.userName);
So where i have the res.cookie is where i want to be able to read and write cookies, any help is appriciated
I think what you are looking for is the middleware pattern employed by express. You can define as many of these middleware calls as you wish, and they are the perfect scope for calling any other functions which may need the res instance (or the req instance for that matter).
app.use(function (req, res, next) {
// call function, passing in res here
next();
})
Reference: https://expressjs.com/en/guide/using-middleware.html
EDIT:
This answer is not correct for your situation. In a node/express server not using socket connections, then yes, you could easily use the above pattern anywhere you need the request and response objects in scope.
However, once you setup the socket io server, the game changes. During the socket communications, there are no express request and response objects in scope anymore, everything is handled directly between your socket handling code and the client. So the answer is you need to handle the situation in a socket io way, not in an express way.
Please see: Adding a cookie value on Socket.IO

Express and Cheerio/JSDOM

I am trying to get Cheerio to work with Express.
I'd like to be able to manipulate the dom from the server, but all I have found is web scraping..
There are some requirements..
At the moment, I am able to run multiple app.listen(port); statements, and use multiple servers.
I'm trying to append <script>alert("test);</script> to every single page sent by express.
I've created the express server: (Assuming Path is a predefined variable)
var express = require('express');
var app = express();
app.get('/', function (req, res) {
app.use(app.static(Path));
res.sendFile(Path + "/index.html");
});
app.listen(Port);
Can you guys provide me with a working example to append this to the page. Is there a way to get this to work in real time?
Thanks!
Here's a quick/simple example with no error handling:
var express = require('express');
var fs = require('fs');
var cheerio = require('cheerio');
var app = express();
app.get('/', function (req, res) {
fs.readFile(Path + '/index.html', function(err, data) {
var $ = cheerio.load(data);
$('body').append('<script>alert("test");</script>');
res.send($.html());
});
});
app.listen(Port);
I just tested that locally and it worked as expected. Be sure to test err inside the readFile callback in your real implementation and handle things appropriately if the file isn't found or there's an error reading it.

NodeJS/Express app.use sequence and usage

I tried to separate my node routing into two parts: HTML/App and REST. Here is what I've done:
app.js:
var appPort = process.env.PORT || 80;
var express = require('express');
var http = require('http');
var appRouter = require('./routes/index');
var restRouter = require('./routes/rest');
var app = express();
var srv = http.createServer(app);
app.set('port', appPort);
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api/rest/', restRouter); // this seems not working .. I never get the expected response
app.use('/', appRouter); // I get this even with localhost/api/rest/...
var server = srv.listen(app.get('port'), function() {
debug('Express server listening ' + server.address().address + ':' + server.address().port);
});
index.js:
var express = require('express');
var router = express.Router();
router.get('/*', function (req, res) {
res.send('HOME')
});
module.exports = router;
rest.js
var express = require('express');
var router = express.Router();
router.get('/api/rest/*', function(req, res) {
res.send('REST API');
});
module.exports = router;
My questions:
1. It's possible in general to build multiple routers in this way?
2. Does the sequence of get.use matter, and/or do I have to deal with 'next'?
3. In case I would like to access a database inside the router can I hand over a parameter like this:
// ...
var client = new pg.Client(dbConnection);
// ...
app.use('/', appRouter(client));
1) It is possible to build multiple routers this way.
Because you are using this:
app.use('/api/rest/', restRouter);
your route calls in rest.js will be relative to /api/rest/ which means your code should be modified in rest.js to look like this:
router.get('*', function(req, res) {
res.send('REST API');
});
I would also encourage you to see the Express multi-router example on GitHub. It illustrates this point very clearly by showing a REST app with versioned routes.
2) The order of things matter
See the Express documentation for app.use and you will note:
Middleware functions are executed sequentially, therefore the order of
middleware inclusion is important.
If you reverse the order of your app.use calls, the router.get('/*', function (req, res) { line in index.js will catch everything before you get to other routes...defeating your purpose.
Also, if you don't call next, Express has no way to know that you are done or even that you want to continue to the next middleware or route.
3) The database question is a modules/scope question
This is more of a scope question than an Express question. I'd suggest looking up some of the excellent writing about javascript scope and also on how Node handles modules.

Categories

Resources