app = express();
I established a socket connection after app.use(), and I want to insert another middleware after socket is connected:
const app = express();
app.use('/', () => {});
const wss = new ws.Server({ port: 8086 });
wss.on('connection', (ws) => {
app.use((req, res, next) => {
ws.send(JSON.stringify({ req, res }));
next();
});
});
app.listen(8080);
but it doesn't work,can Express insert a middleware after app init?
one solution is to make a middleware that checks if a new middleware is added. check the following example.
//this is an array of functions which will work as a middlware.
let listOfMiddlewareFunctions = [];
app.use((req, res, next) => {
//this middleware will loop through all elements in listofMiddlewareFunctions
//and pass the parameters req, res, next to each middlewares.
listOfMiddlewareFunction.foreach(middleware => middleware(req, res, next));
});
wss.on('connection', (ws) => {
//on socket connection, the following will add the middleware to the array made before.
const newMiddleware = (req, res, next) => {
ws.send(JSON.stringify({ req, res }));
next();
};
listOfMiddlewareFunction .add(newMiddleware);
});
finally, I fixed this problem:
wss.on('connection', function (ws) {
app._mockUsedWsSend = ws.send.bind(ws);
});
// in router
const wsSend = req.app._mockUsedWsSend;
if (wsSend) {
wsSend(JSON.stringify({
path: req.path
}));
}
Related
server.js
const express = require("express");
const cookieSession = require("cookie-session");
const socketIo = require("socket.io");
const app = express();
app.use(
cookieSession({
name: "session",
keys: ["key1", "key2"],
})
);
app.use((req, res, next) => {
console.log(req.session);
next();
});
app.get("/", (req, res) => {
res.sendFile("./index.html", { root: __dirname });
});
app.get("/about", (req, res) => {
const connectionId = req.session.connectionId;
res.send(`About. connectionId: ${connectionId}`);
});
const server = app.listen(1234);
const io = socketIo(server);
io.on("connection", (socket) => {
const connectionId = Math.random().toString(36).substring(2);
socket.request.session.connectionId = connectionId;
// socket.request.session.save();
});
My problem is that when I call the connect event on the client, but on the server socket.request.session returns undefined so I can't set a unique value in the cookie-session. What is it connected with?
I am trying to construct a middleware and then use it within the app.get route.
I know it's looks very "pioneer" but i am learning.... How can io get it to work?
const BooksMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/? q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
const data = result.data;
const books = data.items;
return books;
});
next();
}
module.exports = textMiddle;
app.get("/", textMiddle, (req, res, next) => {
res.render('index');
});
If the point of this middleware is to get some book data and make that available for your template rendering, then you can put that data into res.locals where templates called from res.render() will automatically look for data:
const bookMiddle = async (req, res, next) => {
axios
.get(`https://www.googleapis.com/books/v1/volumes/?q=${term}&keyes&key=${process.env.GBOOKSKEY}`)
.then((result) => {
res.locals.books = result.data.items;
next();
}).catch(next);
}
module.exports = bookMiddle;
And, then after you import bookMiddle, you can use it like this:
app.get("/", bookMiddle, (req, res, next) => {
res.render('index');
});
If you refer to the books data structure in your template, the template engine will look in res.locals.books for that data (where the middleware puts the data).
I'm trying to use the Express Router with Next.js using their custom-express-server example as my boilerplate. The only difference is that I'm trying to define the routes externally on routes/router.js as follows:
Code in server.js:
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const routes = require('./routes/router')
app.prepare()
.then(() => {
const server = express()
server.use('/', routes)
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
module.exports = app;
Code in routes/router.js:
const express = require('express'),
app = require('../server.js'),
router = express.Router();
router.get('/a', (req, res) => {
return app.render(req, res, '/b', req.query)
})
router.get('/b', (req, res) => {
return app.render(req, res, '/a', req.query)
})
router.get('/posts/:id', (req, res) => {
return app.render(req, res, '/posts', { id: req.params.id })
})
module.exports = router;
At this point, even when I'm importing "app" from server.js, app is not available within router.js.
Is my logic incorrect?
If it's not, then why is app not available within router.js?
Just solved it. This issue is known as a circular dependency, and it should be avoided at all costs... unless the pattern you're using (like the boilerplate I used, I guess...) requires it.
To solve it, just export from file "A" the dependency that file "B" uses before you require file "B" on file "A".
...And that's it pretty much.
You might also try using next-routes, which I use on all of my Next project:
// server.js
const { createServer } = require('http');
const next = require('next');
const routes = require('./routes');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare().then(() => {
createServer(handler).listen(port, err => {
if (err) {
throw err;
}
console.log(`> Ready on http://localhost:${port}`);
});
});
Then you can configure your routes in the routes.js file without accessing the app:
// routes.js
const nextRoutes = require('next-routes');
const routes = (module.exports = nextRoutes());
routes
.add('landing', '/')
.add('blog', '/blog', 'blog')
.add('blog-post', '/blog/:postId', 'blog')
So i have been racking my brain for quite awhile now trying to figure this out and I'm still having issues.
So i define a route like this:
var home = require('./routes/home');
var app = express();
app.use('/home/:client', home);
And my home.js code looks like this:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('homeview', { title: 'Welcome',
user: username});
});
router.get('/:client', function(req, res, next) {
var theClient = req.params.client;
console.log(theClient)
});
module.exports = router;
And then when i try to go to this URL:
http://www.localhost:3000/home/client
Nothing happens. For some reason it never gets to the second router.get and never logs anything. Anyone notice whats wrong?
Working solution # https://github.com/rmjoia/expressRoutes
app.js
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
homeRouter = require('./home');
app.use('/home', homeRouter);
app.route('/')
.all(function (request, response, next) {
// Do some plumbing stuff
next();
})
.get(function (request, response, next) {
response.send('OK GET - Hello Stack Overflow');
next();
});
app.listen(port, function (error) {
if (error) {
console.error(error.message);
}
else {
console.info('Server up and running. Listening on port ' + port);
}
})
home.js
var express = require('express');
var homeRouter = express.Router();
var router = (function (router) {
// define the home page route
router.get('/', function (req, res) {
res.send('home route - homepage');
});
// define the about route
router.get('/:client', function (req, res) {
res.send(req.params.client);
});
return homeRouter;
})(homeRouter);
module.exports = router;
I am relatively new to MEANJS, i have also been reading through its documentation to learn more.
so, i am trying to create a rest API using meanjs using its yo generator and removing the angular parts of it, so far it has been a success.
What i am trying to do now is to default the url routes to have a prefix of /api/:version, what i did so far is to append the /api/:version to the routes inside app/ like the following
//app/routes/articles.server.routes.js
'use strict';
...
module.exports = function(app) {
// Article Routes
app.route('/api/:version/articles')
...
app.route('/api/:version/articles/:articleId')
...
// Finish by binding the article middleware
app.param('articleId', articles.articleByID);
};
That works so far, but can i declared this somewhere so that i don't have to add /api/:version every time i create a new route?
I tried implementing the ones stated in express documentation and Remi M's answer in this stackoverflow question with no luck.
Update
meanjs installation comes with an express.js, so i thought that this is the right place to do it and i tried using the router object to solve this problem, although it doesn't work
//config/express.js
'use strict';
...
var express = require('express');
...
var router = express.Router();
module.exports = function(db) {
var app = express();
...
app.use(function(req, res, next) {
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
next();
});
app.use(compress({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
...
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
app.use(function(err, req, res, next) {
if (!err) return next();
console.error(err.stack);
res.status(500).render('500', {
error: err.stack
});
});
app.use(function(req, res) {
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found'
});
});
...
app.use('/api/:version', router); //this is what i add
return app;
};
All of your initial configurations should be on router object and not on app For Ex :
'use strict';
var express = require('express');
var router = express.Router();
module.exports = function(db) {
var app = express();
router.use(function(req, res, next) {
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
next();
});
router.use(compress({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(router);
});
router.use(function(err, req, res, next) {
if (!err) return next();
console.error(err.stack);
res.status(500).render('500', {
error: err.stack
});
});
router.use('/bar', function(req, res, next) {
console.log("bar endpoint called");
res.send("bar");
});
router.use(function(req, res) {
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found'
});
});
app.use('/api/:version/', router); //this is what i add
return app;
};
Then call app.use("prefixurl",router) as above.
test the BAR API /api/v1/bar