Create nodejs express 4 route on runtime - node.js

I am trying to create a route on runtime. I am trying to create a flat url structure so if we add an article it will create a slug for it and will create a new route.
I use express 4 new router function
app.js
var express = require('express');
var routes = require('./routes.js');
app.use('/', routes);
var server = http.createServer(app).listen(app.get('port'));
routes.js
var express = require('express');
var router = express.Router();
router.get('/new' ,site.new);
module.exports = router;
I tried creating a function in the router and calling it from the app.js also creating a function in the router while sharing the app instance accross the files
module.exports = app;
and calling it
var app = require("./app.js");
It doesnt seem to work any other idea ?
update:
I have a file called helpers.js and i added the following function
module.exports={
addRoute:function(){
var express = require('express');
var router = express.Router();
var app = require('../app.js');
var routes = require('../routes.js');
router.get('/book', function (req, res) {
res.send('Hello World!');
});
app.use('/book', router);
},
I end up doing that
addRoute:function(){
var express = require('express');
var router = express.Router();
var routes = require('../routes.js');
var app = require('../start-freedom1.js');
router.get('/book' ,function (req, res, next) {
res.send({"data":"kaki","values":"","errors":""});
});
for(var layer in app._router.stack){
if(app._router.stack[layer].name=="router"){
app._router.stack[layer].handle.stack.splice(0, 0, router.stack[0]);
console.log(app._router.stack[layer].handle.stack)
break;
}
}
// / app.use('/', routes);
},
the problem that i had router.get("*"..... at the end of the rout file so i always saw 404

I think that what you are looking for is passing parameters in the URL which you can extract and then use to do some processing. You can do something like below:
app.get('/article/:article_id', function(req, res){
art_id = req.params.article_id;
//query database using art_id
}
If you want to use query parameters instead (with "...../article?id=234") then you would have to use req.query. Have a look at the following page http://expressjs.com/en/api.html#req.params.
Request parameters are considered best practice as they are more readable and are also SEO friendly. You can edit your model to store the article slug as a field but should be unique, that way they can be used to query your DB.

Related

Nodejs Express: Routes in separate files

I write my app.js including all the routes in the main file and everything was working well. After my goal was to make the project more clear by moving the routes in a different files but it is not working.
I'm passing an object instead of a middleware function and I don't know how to fix it in the right way.
So this is my app.js file:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
var myRoutes = require('./app/routes/myRoutes.js');
...
//parser for getting info from POST and/or URL parameters
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//for log requests to console
app.use(morgan('dev'));
app.use('/myRoutes', myRoutes);
app.get('/',function(req,res){
res.end('Welcome Page!');
});
//Server Start
app.listen(port);
console.log('server start at port ' + port);
And the app/routes/myRoutes.js contains the following code:
var express = require('express');
...
var myRoutes = express.Router();
myRoutes.get('/users',function(req,res){
...
});
myRoutes.post('/setup',function(req,res){
...
});
myRoutes.post('/remove', function(req,res){
...
});
module.export = myRoutes;
I also tried this:
var express = require('express');
var myRoutes = express.Router();
myRoutes.route('/')
.get(function(req, res, next){
res.end('myRoute Get');
})
.post(function(req, res, next){
res.end('myRoute Post');
});
module.export = myRoutes;
But again it seems not passing a middleware function.
My second option code
var express = require('express');
var myRoutes = express.Router();
myRoutes.route('/')
.get(function(req, res, next){
res.end('myRoute Get');
})
.post(function(req, res, next){
res.end('myRoute Post');
});
module.export = myRoutes;
is working fine! I just write it in a wrong way
module.export = myRoutes;
isntead of
module.exports = myRoutes;
Hi this is more of additional tips on the question. You main js file would definately need to load a lot of routes and i found importing all of them is a lot of work. Rather use require-dir module to load all the routes like
const loader = require('require-dir');
var app = express();
var routes = loader('./routes');
for (route in routes){
app.use("/"+route,routes[route]);
}
needless to say define all routes inside routes folder and export Router module in each one of them like
var router = express.Router();
router.get(....);
module.exports = router;

Express call GET method within route from another route [duplicate]

This question already has answers here:
Calling Express Route internally from inside NodeJS
(5 answers)
Closed 3 years ago.
I have multiple routes. How can I get the data from the user's route (GET method), by calling it within the GET method of the group's route? What is the best way of doing this?
My app.js looks like this:
var express = require('express');
var routes = require('./routes/index');
var users = require('./routes/users');
var groups = require('./routes/groups');
var app = express();
app.use('/', routes);
app.use('/users', users);
app.use('/groups', groups);
module.exports = app;
app.listen(3000);
Then I have another file routes/users.js:
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('GET ON THE users!');
});
module.exports = router;
And another route routes/groups.js:
var express = require('express');
var router = express.Router();
var otherRouter = require('./users')
/* GET groups listing. */
router.get('/', function(req, res, next) {
// call the get on users and retrieve all data from that request
res.send('GET for the groups');
});
module.exports = router;
You shouldn't use routing for that. Just call the function responsible for retrieving the users from the GET groups route and do what you need with that data. The way you propose is much more expensive because you will have to make a http call.
For simplicity I'm assuming that your logic is synchronous and data stored in data/users.js:
var data = [{id:1, name: "one"},{id: 2, name: "two"}];
module.exports = function(){
return data;
};
in routes/users.js:
var express = require('express');
var router = express.Router();
var getUsers = required('./../data/users');
router.get('/', function(req, res, next) {
res.send(getUsers());
});
in routes/groups.js:
var express = require('express');
var router = express.Router();
var otherRouter = require('./users')
var getUsers = require('./.../data/users');
router.get('/', function(req, res, next) {
var users = getUsers();
//do some logic to get groups based on users variable value
res.send('GET for the groups');
});
I consider what was being explained "forwarding", and it's quite useful, and available in other frameworks, in other languages.
Additionally, as a "forward" it does not have any overhead from a subsequent HTTP response.
In the case of Express, the following is available in version 4.X. Possibly other versions, but I have not checked.
var app = express()
function myRoute(req, res, next) {
return res.send('ok')
}
function home(req, res, next) {
req.url = '/some/other/path'
// below is the code to handle the "forward".
// if we want to change the method: req.method = 'POST'
return app._router.handle(req, res, next)
}
app.get('/some/other/path', myRoute)
app.get('/', home)
You can use run-middleware module exactly for that
app.runMiddleware('/pathForRoute',{method:'post'},function(responseCode,body,headers){
// Your code here
})
More info:
Module page in Github & NPM;
Examples of use run-middleware module
Disclosure: I am the maintainer & first developer of this module.
For people coming here from google. If you need to hit one or more of your routes and skip the http request you can also use supertest.
const request = require("supertest");
app.get("/usersAndGroups", async function(req, res) {
const client = request(req.app);
const users = await client.get("/users");
const groups = await client.get("/groups");
res.json({
users: users.body,
groups: groups.body
});
});
You can also run them concurrently with Promise.all
I've made a dedicated middleware for this uest, see my detailed answer here: https://stackoverflow.com/a/59514893/133327

Combine routes from multiple files in ExpressJS?

What is the best way to combine routes from two files so Express Router will handle them at the same level? I'm thinking of something like this:
Default Routes File
This file would be generated and overwritten every time the generator runs:
var express = require('express'),
router = express.Router(),
custom = require('./custom.routes');
router.get('/', function (req, res) {
});
router.post('/', function (req, res) {
});
router.put('/', function (req, res) {
});
router.use('/', custom);
module.exports = router;
Custom Routes File
This file would only be generated the first time and would never be overwritten.
var express = require('express'),
router = express.Router();
router.post('/custom-method', function (req, res) {
});
module.exports = router;
Parent Route File
This file is generated and overwritten constantly. It is responsible for providing the top level api route:
var express = require('express'),
apiRouter = express.Router();
var widgetRouter = require('./widget.routes');
apiRouter.use('/widgets', widgetRouter);
var sprocketRouter = require('./sprocket.routes');
apiRouter.use('/sprockets', sprocketRouter);
module.exports = apiRouter;
The obvious goal is to allow the developer to customize the routes and know his work will be safe even when the generator is run again.
router.use() does not necessarily need to take you deeper in the tree. You could just add the following line before the exports of the first file.
router.use('/', require('./routes.custom.js'));
With this you can also remove the wrapper from the custom file.

Multiple module.exports

I have this code here
var router = require('./Router/index')(app, passport);
Im passing app and passport to my index.js file
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute'));
// Website
app.use('/', require('./Routes/Website'));
app.use('/keys', require('./Routes/KeysRoute'));
app.use('/users', require('./Routes/UsersRoute'));
};
Im going to use passport in my website route file
var express = require('express');
var router = express.Router();
var Users = require('../../Class/Users');
router.get('/CreateUser', function (req, res) {
Users.getUsers(function(result){
res.render('NewUser');
});
});
module.exports = router;
How can i pass the passport object over to be used in my website route file?
You can use the pattern further of exporting a function. Though, instead of exporting the router, the function can return it.
var express = require('express');
var Users = require('../../Class/Users');
module.exports = function (passport) {
var router = express.Router();
// ...
return router;
};
Then, invoking the exported function to pass along passport from index.js:
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute')(passport));
// ...
module.exports = function (app,passport) {
// App's API
app.use('/api', require('./Routes/AppRoute'));
// Website
app.use('/', require('./Routes/Website')(passport));
app.use('/keys', require('./Routes/KeysRoute'));
app.use('/users', require('./Routes/UsersRoute'));
};
You Website route file
var express = require('express');
var router = express.Router();
var Users = require('../../Class/Users');
module.exports = function (passport) {
router.get('/CreateUser', function (req, res) {
Users.getUsers(function(result){
res.render('NewUser');
});
});
}

How can I make one page in my node.js app use multiple route files?

Sorry ahead of time if this sounds confusing, or has been answered before.
Using node.js, express and express-generator, I created an app that has two route files:
The first route file does MySQL database interaction and returns the result of queries (used for displaying data on the home and admin pages).
The second route file uses an LDAP server for checking login credentials, as well as managing login sessions (used for checking authorization on the login and admin pages).
Both routes requires express to function, but if I require express in both route files it gives me an error. Is there a way to allow both route files to use the same express router?
app.js
var express = require('express');
// Other generated requires
var data = require('./routes/data');
var auth = require('./routes/auth');
var app = express();
// Other generated sets and uses
app.use('/', data);
// "login" and "admin" need to use both data.js and auth.js <----------------
//app.use('/login', data);
//app.use('/login', auth);
//app.use('/admin', data);
//app.use('/admin', auth);
module.exports = app;
routes/data.js
var express = require('express');
var router = express.Router();
// Database functions
router.get('/', function (request, response) {
response.render('index');
});
module.exports = router;
routes/auth.js
var express = require('express');
var session = require('express-session');
var directory = require('activedirectory');
var router = express.Router();
// Login and session functions
router.get('/login', function (request, response) {
// Login and session check
response.render('login');
});
router.get('/admin', function (request, response, next) {
// Session check
response.render('admin');
});
module.exports = router;

Resources