Here's a modified example from Express.js's routing guide:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('Birds home page');
});
router.get('/about', function(req, res) {
res.send('About birds');
});
...
app.use('/birds', router);
app.use('/fish', router);
This prints "About birds" when I visit both /birds/about and /fish/about.
How do I pass a parameter or something to the router so, in the controller functions, it can tell those two different routes apart?
For example, I'd like to see "Birds can fly" when visiting /birds/about and "Fish can swim" when visiting /fish/about.
Ideally, I'd like to be able to pass some "configuration object" so the mini-app does not need to know about all possible routes it may be mounted at (in pseudocode):
router.get('/about', function(req, res) {
res.send(magic_configuration.about_text);
});
....
magically_set_config(router, {about_text: "Bears eat fish"})
app.use('/bears', router);
Here's what I've come up with: I pass the "mini-app configuration" by assigning it to req:
app.use('/birds', function (req, res, next) {
req.animal_config = {
name: 'Bird',
says: 'chirp'
};
next();
}, animal_router);
app.use('/cats', function (req, res, next) {
req.animal_config = {
name: 'Cat',
says: 'meow'
}
next();
}, animal_router);
and then in my route I can access them:
var express = require('express');
var router = express.Router();
...
router.get('/about', function(req, res) {
var animal = req.animal_config;
res.send(animal.name + ' says ' + animal.says);
});
This approach allows to easily mount the "mini-app" at another location providing different configuration, without modifying the code of the app:
app.use('/bears', function (req, res, next) {
req.animal_config = {
name: 'Bear',
says: 'rawr'
};
next();
}, animal_router);
You're basically talking about injecting configuration to a router.
I have faced with similar problem and figured out that in theory you can export not a router itself, but rather function that accepts configuration and returns created and configured router.
So in your case calling code will look like:
var animal_router = require('./animal_router')
app.use('/birds', animal_router({
name: 'Bird',
says: 'chirp'
}));
app.use('/cats', animal_router({
name: 'Cat',
says: 'meow'
}));
While ./animal_router.js might look following:
var express = require('express');
// Create wrapper function that will adjust router based on provided configuration
var wrapper = function (animal_config) {
var router = express.Router();
router.get('/about', function(req, res) {
var animal = animal_config;
res.send(animal.name + ' says ' + animal.says);
});
return router;
}
module.exports = wrapper;
So, if you want to serve changes by url, then you can inject params like this:
router.get('/:animal/about', function(req, res) {
// here we have bird or fish in req.params.animal
if(req.params.animal == 'bird') {
res.send('Birds can fly');
} else if(req.params.animal == 'fish') {
res.send('Fish can swim');
} else {
res.send('Unknown animal');
}
});
app.use('/', router);
You can use req.baseUrl to figure that out.
You can add route params like so:
router.get('/about/:param1/:param2', function(req, res) {
//then you can call this handler through /about/1/sometext get these params from request object:
console.log(req.params.param1, req.params.param2); // 1, 'sometext'
res.send('About birds');
});
Or you can send parameters through query params:
router.get('/about', function(req, res) {
//then you can call this handler through /about?param1=1¶m2=sometext get these params from request object as well:
console.log(req.query.param1, req.query.param2); // 1, 'sometext'
res.send('About birds');
});
Related
I'm creating my routes module in nodejs with socket.io
var express = require("express"); // call express
var taskSchema = require("../models/taskModel");
var mongoose = require("mongoose");
var router = express.Router(); // get an instance of the express Router
module.exports = function (io) {
router.use(function (req, res, next) {
io.sockets.emit('payload');
console.log("Something is happening.");
next();
});
router
.route("/tasks")
.post(function (req, res, next) {
...
});
router
.route("/tasks")
.get(function (req, res) {
...
});
};
When I compile server I get this error
TypeError: Router.use() requires a middleware function but got a undefined
It appears to me that the problem is probably in the code that loads this module because you never export the actual router. So, assuming you do app.use() or router.use() in the caller who loads this module, your aren't returning the router from your function so there's no way to hook that router in and you would get the error you see.
I'm guessing that you can fix this by just returning the router from your exported function:
var express = require("express"); // call express
var taskSchema = require("../models/taskModel");
var mongoose = require("mongoose");
var router = express.Router(); // get an instance of the express Router
module.exports = function (io) {
router.use(function (req, res, next) {
io.sockets.emit('payload');
console.log("Something is happening.");
next();
});
router
.route("/tasks")
.post(function (req, res, next) {
...
});
router
.route("/tasks")
.get(function (req, res) {
...
});
return router; // <=========== Add this
};
Then, when you do:
let m = require('yourModule');
router.use(m(io));
Then function will return the router that router.use() will be happy with. You can pass either middleware or a router to .use().
If this guess isn't quite on target, then please show us the code that loads and calls this module.
When that function is called it's gonna return the equivalent of undefined. Also, normally a route is defined before the endpoint. It's typically structured like:
let myRouter = new Router();
Router.use('something', middlewareFunction, someotherprocess);
i come to you because i'm stuck for rewrite my url in javascript.
For example when user make a request for deposit page , my url looks like '/member/deposit' but i just want '/deposit'. i'm using a MVC architecture.
index.js // Where i define all routes file
const
homeRoute = require('./home'),
memberRoute = require('./member');
function init(server) {
server.get('*', function (req, res, next) {
res.locals.user = req.user || null;
return next();
});
server.use('/', homeRoute);
server.use('/member', memberRoute);
}
module.exports = {
init: init
};
router member.js // Where i define all member routes
const
express = require('express'),
memberController = require('../controllers/member');
let router = express.Router();
router.get('/*', function(req, res, next){
if (req.session.user && (req.session.user.role == "member"))
next();
else
res.redirect('/login');
});
router.get('/', memberController.deposit);
router.get('/deposit', memberController.deposit);
router.get('/withdraw', memberController.withdraw);
module.exports = router;
controller member.js // where all code is executed before rendering
function deposit(req,res){
res.render('member/deposit',{
title:'Deposit'
});
}
function withdraw(req,res){
res.render('member/withdraw',{
title:'Withdraw'
});
}
Any help would be appreciated, i've not find response on stackoverflow
It can be use this way:
server.use('/', homeRoute);
server.use('/', memberRoute);
As long as the link in homeRoute and memberRoute have no duplication.
Or
The complete rewrite of url can be done as in the following link:
https://gist.github.com/ramonfritsch/06893c1c561d670687a9aee3bbc4e9c7
I try print router parametrs but req.params is empty, don't know what I'm doing wrong.
In app.js:
...
var shareFile=require('./controllers/file/share');
...
app.use('/share/:id', shareFile);
...
And share.js controller:
var express = require('express');
var router = express.Router()
router.get('/', function (req, res, next) {
res.send(req.params)
});
module.exports = router;
localhost:3000/share/123 gives empty json page. Changing res.send to console.log gives {}.
Thanks
req.params will produce {id: 'abc'} when the routing is defined as /share/:id and you made the call to http://yourserver/share/abc
router.get('/', function (req, res, next) {
res.send(req.params)
});
Above you should expect that req.params will be empty here because your are not expecting them. But you should see them here:
router.get('/share/:id', function (req, res, next) {
res.send(req.params)
});
Trying to get URl parameters in express js,but got empty object.
var password= require('./routes/password');
app.use('/reset/:token',password);
password.js
router.get('/', function(req, res, next) {
console.log(req.params);
res.send(req.params);
});
console.log(req.params) output is {}
Access url :http://localhost:3000/reset/CiVv6U9HUPlES3i0eUsNwK9zb7xVZpfHsQNuzMNWqLlGA4NJKoagwbcyiUZ8
By default, nested routers do not get passed any parameters that are used in mountpaths from their parent routers.
In your case, app is the parent router, which uses /reset/:token as a mountpath, and router is the nested router.
If you want router to be able to access req.params.token, create it as follows:
let router = express.Router({ mergeParams : true });
Documented here.
You are getting params and query mixed up.
Query approach
Your code should look like this when using query values for the example url: www.example.com?token=123&foo=bar
router.get('/', function(req, res, next) {
console.log(req.query);
console.log(req.query.token); // to log value of token
console.log(req.query.foo); // to log value of foo
res.send(req.query);
});
Params approach
Your code should look like this when using params values for the example url: www.example.com/123
router.get('/:token', function(req, res, next) {
console.log(req.params);
console.log(req.params.token); // to log value of token
res.send(req.params);
});
Instead you can use a middleware to log the path params:
const logger = (req, res, next)=>{
console.log(req.params)
res.send(req.params)
next()//<----very important to call it.
};
app.use(logger); //<----use to apply in the app
router.get('/', (req, res, next)=>res.send('Logged.'));
Actually you messed it up a little bit. You have to pass instance of express to your module.
Server.js:
//adding modules
require('./routes/password')(app);
Password.js:
module.exports = function(router) {
router.get('/reset/:token', function(req, res, next) {
console.log(req.params);
res.send(req.params);
});
//and so on.. your routes go here
}
I'm new to express and I've gone through a tutorial that had me add routes like this:
var index = require('./routes/index');
var foods = require('./routes/foods');
and use them like this:
app.use('/', index);
app.use('/api', foods);
I'm to the point now where I want to add another route under the /api path, but I'm not sure how to do this semantically. Something like this (though this doesn't work)
server.js
var index = require('./routes/index');
var foods = require('./routes/foods');
var foods = require('./routes/users');
...
app.use('/', index);
app.use('/api', [foods, users]);
this should allow me to have routes like:
/api/food/:id, /api/foods from foods.js
/api/user/:id, /api/users from users.js
The URL has to be unique unless you use the http verbs to specify the intent.
var foods = require('./routes/foods');
var users = require('./routes/users');
app.get('/api/foods', foods);
app.get('/api/users', users);
app.post('/api/foods', function(req, res) { /* other function */ });
UPDATE
Lets say you want to divide out your business logic in separate files, you can accomplish this with the following:
foods.js
module.exports = {
getAll: function(req, res) { ... },
getItem: function(req, res) { ... },
addItem: function(req, res) { ... }
};
users.js
module.exports = {
getAll: function(req, res) { ... },
getItem: function(req, res) { ... }
};
server.js
var foods = require('./routes/foods');
var users = require('./routes/users');
app.get('/api/food/:id', foods.getItem);
app.get('/api/foods', foods.getAll);
app.post('/api/foods', foods.addItem);
app.get('/api/user/:id', users.getItem);
app.get('/api/users', users.getAll);
I personally like to have the routes listed in a file, it gives you a quick lookup for which routes you support with which verbs. notice I've created an extra function for adding new food items.
I hope this update helps