Routing in Express.js - node.js

I am currently express router in Node.js and having a problem like below. Let's say I have two url; one is to get a user info and one is to register users to an application.
http://example.com/users/:idUser (this will give a information of a user)
http://example.com/users/registration (this will allow a user registration)
The problem I have facing is when I call registration, the router is working with idUser; so I had to edit like user/registration instead of users. If I want to use as users/registration, which kinds of work do I have to do. I am still a newbie in Node.js.
Thanks.

You need to order the routes appropriately so that the registration route comes before.
app.get('/users/registration', function(req, res, next) {
....
});
app.get('/users/:userId', function(req, res, next) {
....
});

Just invert the order, like this:
app.get('/users/registration', function(req, res, next) {
...
});
app.get('/users/:userId', function(req, res, next) {
...
});

Related

How to pass one of multiple middleware nodejs

I have a router like this
router.post("/roomplayers",[authjwt.verifyTokenAdmin,authjwt.finishedRoomManagement,authjwt.activeRoomManagement],
RoomController.findPlayers)
and I would to get the controller RoomController.findPlayers if the admin have this cofinishedRoomManagementdepermission
OR this activeRoomManagement
How can I do that
If your question is how to pass through many middleware's in your route the solution is below.
const tokenMiddleWare = (req, res, next) =>{
//Your code here
next();
}
const isAdminMiddleWare = (req, res, next)=>{
//Your code here
next();
}
So now that we have two middlewares and one controller(I omitted it though) now you can work on route and pass those middlewares and controller but before I start I want point something important
So with the next you want to push the user down out of the middleware driving them closer to the route that they want to hit only when they meet all you validation that's when you want to push them down
router.post('/api/login', tokenMiddleWare, isAdminMiddleWare, (req, res)=>{
authController.login(req, res);
})
Now this would be how you pass down multiple middlewares and using your controller

Handling different routes that start similarly in NodeJS, Express

I'm creating an API which have Articles and Comments belonging to those articles.
const articleRoutes = require('./api/routes/articles');
const commentRoutes = require('./api/routes/comments');
then
app.use('/articles', articleRoutes);
app.use('/comments', commentRoutes);
Anything starting with "articles/" gets forwarded to articleRoutes, and anything starting with "comments/" gets forwarded to commentRoutes.
Comment GET requests are like
/comments?article=ID_OF_ARTICLE
Like this everything is working perfectly.
However
I want to restructure the comments route to be like
/articles/ID_OF_ARTICLE/comments
However now they both start with "/articles"
How would I deal with this?
I would try the following:
app.use('/articles/:id/comments', commentRoutes);
app.use('/articles', articleRoutes);
So I think the order is important in the above.
// inside commentRoutes
Router.get('/', (req, res) => {
let articlesId = req.originalUrl.split('/')[2]
})
I hope this helps
The originalUrl approach seems to work too, But I went with the solution here
Apparently I can do
app.use('/articles/:articleId/comments', function(req, res, next) {
req.articleId = req.params.articleId;
next();
}, commentRoutes);
and in commentRoutes
// in commentRoutes
router.get('/', (req, res, next) => {
let articleId = req.articleId
})
So I can attach the required parameter to the request as a separate entry and access it directly

How to routing for mobile view in express

I want to change the URL for mobile. www.example.com to m.example.com
I use isMobile function to detect device type.
I do not know what to do for routing.
for example: m.example.com/index
please help me
in app.js
function isMobile(req, res, next) {
if ((/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(req.headers["user-agent"]))) {
res.redirect('//m.' + req.host+ req.path);
} else {
next()
}
}
app.get('/',isMobile,routes.index);
If device is a mobile,i want to run routes.mobileindex. How?
If you want to render a separate view for mobile devices in the same application then it would be pretty straigh forward. it is a just a matter of creating another view file and you can apply your separate layout and CSS style to design it.
var express = require("express");
var router = express.Router();
function isMobile(req, res, next) {
if (
/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(
req.headers["user-agent"]
)
) {
// Instead of redirecting to another view you can also render a separate
// view for mobile view e.g. res.render('mobileview');
res.redirect("/mobile/device");
} else {
next();
}
}
/* GET home page. */
router.get("/", function(req, res, next) {
res.render("index", {
title: "Express"
});
});
router.get("/device", isMobile, function(req, res, next) {
res.json("normal view is rendered");
});
router.get("/mobile/device", function(req, res, next) {
res.render("mobile");
});
module.exports = router;
I have set a redirection here but this is not the best way if you are in the same application, because you can directly hit /mobile/device view, in that case you also need a middleware or can reuse the isMobile middleware to redirect to normal view. I would rather suggest to use res.render('yourviewname')
Hope this gives you an idea to proceed futher!

Express 4: router syntax

I am using Express 4 with the new router. At least one thing continues to confuse me, and it is a syntax problem - I am wondering if there is a regex that can do what I want. I have a standard REST api, but I want to add batch updates, so that I can send all the info to update some users models with one request, instead of one PUT request per user, for example. Anyway, I currently route all requests to the users resources, like so:
app.use('/users, userRoutes);
in userRoutes.js:
router.get('/', function (req, res, next) {
//gets all users
});
router.put('/:user_id', function (req, res, next) {
//updates a single user
});
but now I want a route that captures a batch request, something like this:
router.put('/Batch', function (req, res, next) {
//this picks up an array of users from the JSON in req.body and updates all
});
in other words, I want something which translates to:
app.use('/usersBatch, function(req,res,next){
}
...but with the new router. I can't get the syntax right.
I tried this:
app.use('/users*, userRoutes);
but that doesn't work. Does anyone know how to design this?
I'm guessing that the call to [PUT] /users/Batch is being picked up by the [PUT] /users/:user_id route. The string /:user_id is used as a regular expression causing it to also collect /Batch.
You can either move /Batch before /:user_id in the route order, refine the regex of /:user_id to not catch /Batch or change /Batch to something that won't get picked up too early.
(plus all the stuff Michael said)
REST doesn't include a POST as a list syntax. That's because each URL in REST point to an individual resource.
As an internet engineer I haven't seen any bulk PUTs or POSTs, but that said, it's your app, so you can make whatever API you like. There are definitely use cases for it.
You'll still need to describe it to Express. I would do it like this:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {}); // gets all users
router.post('/:user_id', function (req, res) {}); // one user
router.put('/:user_id', function (req, res) {}); // one user
router.patch('/:user_id', function (req, res) {}); // one user
router.delete('/:user_id', function (req, res) {}); // one user
app.use('/user', router); // Notice the /user/:user_id is *singular*
var pluralRouter = express.Router();
pluralRouter.post('/', function (req, res) {
// req.body is an array. Process this array with a foreach
// using more or less the same code you used in router.post()
});
pluralRouter.put('/', function (req, res) {
// req.body is another array. Have items in the array include
// their unique ID's. Process this array with a foreach
// using +/- the same code in router.put()
});
app.use('/users', pluralRouter); // Notice the PUT /users/ is *plural*
There are other ways to do this. Including putting comma-delimited parameters in the URL. E.g.
GET /user/1,2,3,4
But this isn't that awesome to use, and vague in a PUT or POST. Parallel arrays are evil.
All in all, it's a niche use case, so do what works best. Remember, the server is built to serve the client. Figure out what the client needs and serve.

Routes file issues with Passport

I'm using NodeJS, Express, and PassportJS to build a web application. I'm having a problem with one of my routes which I can't make any sense out of. When I have:
...
app.get('/auth/facebook', passport.authenticate('facebook'));
...
Everything seems to work fine. But when I change that to:
...
app.get('/auth/facebook',
function(req, res) {
passport.authenticate('facebook');
});
...
It hangs? Am I missing something on the app.get function? I want to be able to do this because I want to make the path a little more dynamic where I determine what passport authenticates. For example:
...
app.get('/auth/:provider',
function(req, res) {
passport.authenticate(req.params.provider);
});
...
Where provider could be facebook, twitter, or google...
passport.authenticate is middleware, take a gander at the source: https://github.com/jaredhanson/passport/blob/master/lib/passport/middleware/authenticate.js
passport.authenticate('facebook') returns a function that takes the req, res, next parameters from express and handles them.
so:
app.get('/auth/:provider',
function(req, res, next) {
passport.authenticate(req.params.provider)(req, res, next);
});
is what you need.

Resources