How do I POST/GET to the root of a route? - node.js

In my very simple app I have a users route which is hit when I browse to http://localhost/api/users
Is it possible for me to handle a post or get request to that url without appending anything extra to the route? Using the code below the route handler fires when I post to http://localhost/api/users/new but not to http://localhost/api/users and when I try get http://localhost/api/users/13 but not http://localhost/api/users
I know I could use router.post('/', function(req, res) {}); to post to http://localhost/api/users/ but that extra slash seems inelegant
app.js
var express = require('express');
var users = require('./routes/user');
var app = express();
app.use('/api/users', users);
module.exports = app;
routes\user.js
var express = require('express');
var User = require('../models/user');
var router = express.Router();
router.post(function(req, res) {
// post to root
});
router.post('/new', function(req, res) {
// post to /new
});
router.get(function (req, res, next) {
// get root
});
router.get('/:id', function (req, res, next) {
// get /id
});
module.exports = router;

in routes/user.js, you can simply write:
router.post('/', function (req, res, next) {
// post to /api/user or /api/user/
});
router.get('/', function (req, res, next) {
// get /api/user or /api/user/
});
This would work for both: http://localhost/api/users as well as http://localhost/api/users/
Also, there's nothing inelegant about having a / at the end of the url!

You can use an empty route like this :
router.get("", function (req, res, next) {
// get root
});
You will be able to access to /api/user as well as /api/user/

Also you can handle the route with the route method of router to simplify the code and make it more "elegant" :
router.route('/')
.get(function(req, res){}) // GET method of /api/users
.post(function(req, res){}) // POST method of /api/users
.put(function(req, res){}) // PUT method of /api/users
.delete(function(req, res){}) // DELETE method of /api/users
http://expressjs.com/es/api.html#router.route

Related

Express route not working - nodejs

I have a simple scenario. I am following Max tutorial.
My http://localhost:3000/message always returns index page. That is only the first route is working. The new route is not working. I am simply trying to put node.hbs on /message
/routes/app.js
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
res.render('index');
});
router.get('/messsage', function (req, res, next) {
res.render('node', { message: 'hello' });
});
module.exports = router;
app.js
var appRoutes = require('./routes/app');
app.use('/', appRoutes);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
return res.render('index');
});
Your code is working. The requested URL http://localhost:3000/message is not matching any of your declared paths so it is defaulting to your custom 404 page which is the same as your index page. Without changing your code and simply requesting http://localhost:3000/messsage will match the path of /messsage on your router. It's a typo. 😉

Express dynamic include route based on user type

Need some help or any clue including/requiring dynamic routes at runtime in express, its confusing but i try my best.
This is just an example of app routes configuration right now
app.use('/', require('./routes/public'));
app.use('/u', require('./routes/user'));
app.use('/a', require('./routes/admin'));
for example require('./routes/public') will include something like this
router.get('/', home.index);
router.get('/faq', faq.index)
also require('./routes/user') will include this
router.get('/dashboard', user_home.index);
router.get('/accounts', user_acc.index)
also require('./routes/admin')
router.get('/dashboard', adm_home.index);
router.get('/accounts', adm_acc.index)
i have installed passportjs so its easy to check if the user is authenticated, also if it is, user contains 1 property type, eg: 1 = user, 2 = admin.
req.user.type = 1 or 2, req.isAuthenticated()...
what i need is inject depending user type 1 or 2, require('./routes/user') or require('./routes/admin') at runetime, cos i dont want to declare invalid routes for an user type user example including admin, or backwards.
Right now, all routes are visible or valid but i need to check every controller for user type, also i dont want the '/a' OR '/u' routes prefix.
All routes must be under '/'.
Request runs to first matched path. You can render page, throw error or call next to get next middleware. Below some router examples.
'use strict'
var express = require ('express');
var app = express();
var publicRouter = express.Router();
publicRouter.get('/', (req, res) => res.send('ROOT'));
publicRouter.get('/account', function (req, res, next) {
if (!is-user)
res.send('Hello guest')
else
next();
});
var userRouter = express.Router();
function isUser (req, res, next) {
// return next() on user logon, and error otherwise
return next();
}
userRouter.use(isUser);
userRouter.get('/dashboard', (req, res) => res.send('/dashboard'));
userRouter.get('/account', (req, res) => res.send('Hello user'));
var adminRouter = express.Router();
function isAdmin (req, res, next) {
// return next() on admin logon, and error otherwise
return next(new Error('Access denied'));
}
adminRouter.get('/manage', (req, res) => res.send('/manage'));
app.use(publicRouter);
app.use(userRouter);
app.use('/admin', isAdmin, adminRouter); // "/admin/manage", not "/manage"
// error handler
app.use(function (err, req, res, next) {
res.send(err.message);
});
app.listen(2000, () => console.log('Listening on port 2000'));
Another way is
app.get('/', do-smth);
app.get('/dashboard', isUser, do-smth);
app.get('/manage', isAdmin, do-smth);

Node Js : Multiple routes in single router file

Can we define multiple routes in single router file.
e.g : Consider we have company and user tab and I want to define 1 routers file for each tab. All Company related calls should be handled by Company router and User related calls should be handled by User router.
//app.js
app.use('/', require('./routes/user'));
app.use('/api/user/load_user_list', require('./routes/user'));
app.use('/api/user/get_user_detail', require('./routes/user'));
//User.js router
var express = require('express');
var router = express.Router();
//router 1
router.get('/', function (req, res, next) {
//do something here -
});
//router 2
router.get('/api/user/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/api/user/get_user_detail', function (req, res, next) {
//do something here
});
module.exports = router;
Currently, when app receives call for '/api/user/load_user_list' my "router 1" gets called.
Am I missing out something. To deal with this, I guess I can have single router call and delegate to different function based on request baseUrl.
Any help / suggestion will be appreciated.. Thanks
Instead of :
app.use('/', require('./routes/user'));
app.use('/api/user/load_user_list', require('./routes/user'));
app.use('/api/user/get_user_detail', require('./routes/user'));
Just use :
app.use('/', require('./routes/user'))
app.use('/api/user', require('./routes/user'));
And in your router file rename the routes like so :
//router 2
router.get('/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/get_user_detail', function (req, res, next) {
//do something here
});
Reason :
When app.use('/api/user/xyz', require('./xyz')) is called, the uri path after api/user/xyz is sent to the router to be matched
What is happening here is, since you have given /api/user/load_user_list in app.use('/api/user/load_user_list', require('./routes/user'));, express will prefix all the routes inside your ./routes/user with /api/user/load_user_list.
The / router 1 in your user.js becomes /api/user/load_user_list + / and /api/user/load_user_list in your user.js becomes /api/user/load_user_list(from app.js) + /api/user/load_user_list.
So only when you hit /api/user/load_user_list/api/user/load_user_list, your router 2 will be called.
You can change your app.js code to
app.use('/api/user', require('./routes/user'));
and your routes/user.js to
//router 1
router.get('/', function (req, res, next) {
//do something here -
});
//router 2
router.get('/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/get_user_detail', function (req, res, next) {
//do something here
});
Now, when you hit /api/user/load_user_list, it will match /api/user(app.js) + /load_user_list(routes/user.js) and the route which you wanted will be called.

How to pass multiple parameters from controller in node.js express

I am working with Passport, and I need to pass multiple parameters through to from my controller to my router. Basically it only passes the first one.
I want to get
app.get('/auth/steam', controllers.auth.authenticate);
to result in
app.get('/auth/steam', passport.authenticate('steam'), function(req, res) { res.render('index') };);
Right now it only loads the 1st parameter.
My controller looks like this
exports.authenticate =
passport.authenticate('steam'),
function(req, res) {
res.render('index');
};
How would I do this?
EDIT: I want to only be able to call it with controllers.auth.authenticate, not in an array like: controllers.auth.authenticate[0]!
Warning NOT tested.
You can wrap all inside function
exports.authenticate = function(req, res, next) {
passport.authenticate('steam', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/auth/steam'); }
res.render("index");
});
}
Or you can use router and protect ALL verbs (get, post, etc)
var express = require('express');
var router = express.Router();
router.use(function (req, res, next) {
passport.authenticate('steam');
});
router.get('/', function(req, res, next) {
res.render("index");
});
module.exports = router;
And use router on the app
var ctrl = require("yourModuleName");
app.use('/auth/steam', ctrl); // app.use NOT app.get
Other alternative is to protect only the get
var express = require('express');
var router = express.Router();
router.get('/', passport.authenticate('steam'), function(req, res, next) {
res.render("index");
});
module.exports = router;
var ctrl = require("yourModuleName");
app.use('/auth/steam', ctrl); // app.use NOT app.get
See Express routing page

get REST APi response in another route

I'm using Express with generator
I want to use JSON response of Rest Api in another route
like this :
var express = require('express');
var router = express.Router();
router.get('/api/:id', function(req, res, next) {
res.json($something); // generate json object
});
router.get('/show', function(req, res, next){
router.get(/api/12,function(request, response){
res.send(request.body);
});
});
Either you extract the middleware function used for /api/:id/ so you can reuse it (recommended) or you need to issue a proper request. router.get does not request the resource, as you seem to think, it rather sets up a route.
So, I'd go for:
var express = require('express');
var router = express.Router();
var getResource = function(req, res, next) {
//use req.params.id to look up resource
res.json($something); // generate json object
}
router.get('/api/:id', getResource );
router.get('/show', function(req, res, next){
req.params.id = "12";
return getResource(req, res, next);
});

Resources