Difference between adding route keyword in defining route in Express - node.js

What is the difference between
router.route('/create')
.post(validate(hotelValidation.createHotel), function (req, res) {
and simply
router.post('/create', validate(hotelValidation.createHotel), function (req, res) {
Are these the same? What does the route keyword accomplish here?

Are these the same? What does the route keyword accomplish here?
Here it accomplishes nothing. But you could do:
app.route('/some/very/long/path/that/you/dont/want/to/duplicate/risking/errors')
.get(function (req, res) {
})
.post(function (req, res) {
})
.put(function (req, res) {
});
Instead of:
router.get('/some/very/long/path/that/you/dont/want/to/duplicate/risking/errors', function (req, res) {
})
router.post('/some/very/long/path/that/you/dont/want/to/dpulicate/risking/errors', function (req, res) {
})
router.put('/some/very/long/path/that/you/dont/want/to/dulpicate/risking/errors', function (req, res) {
});

router.route(path) creates an instance of a single Route for the given path.
Using router.route(path) is a recommended approach to avoiding duplicate route naming and thus typo errors.
router.[method] like "post" and "get" These are functions which you can directly call on a route to register a new handler for the method on the route.

Related

prevent express middleware from executing for same parent path

This is my code when.
I am hitting put API it is executing middleware 3 times but it should execute for put API only.
app.use('/api/user', MiddlewareFun);
app.get('/api/user', (req, res) => {
//do something
});
app.use('/api/user', MiddlewareFun);
app.post('/api/user', (req, res) => {
//do something
});
app.use('/api/user', MiddlewareFun);
app.put('/api/user', (req, res) => {
//do something
});
please don't say use like this.
app.put('/api/user', MiddlewareFun, (req, res) => {
//do something
});
Well, it's happening, because you've made it to. If you want the middleware, to be executed at only selected method, you have to specify it. For example:
Instead of doing:
app.use('/api/user', MiddlewareFun)
app.put('/api/user', (req, res) => {
//do something
})
replace use method with put. As you'd bind regular route:
app.put('/api/user', MiddlewareFun)
app.put('/api/user', (req, res) => {
//do something
})
Also, one more thing. You don't have to duplicate your middleware call before every route declaration. If you want to apply a middleware to your whole router, you can use .use() (as you did), or .all(); which will result in the same behavior.
The middlewares in Express are binded to app or to router.
The solution to yuur problem is to check the method of the request object at the middleware
let MiddlewareFun = function (req, res, next) {
if (req.method === 'PUT') {
// do something
}
next()
}
app.use('/api/user', MiddlewareFun);
The answer is, You need to write express middleware which is part of your app or router. You can write as many middlewares you want, but in your case you just need it only once and here is the implementation of that.
const MiddlewareFun = function(req, res, next) {
// req is object which consist of information about request made.
// From req object you can get method name which is called.
if(req.method.toLowerString() === 'put') {
// your logic goes here
}
next();
}
app.use('/api/user', MiddlewareFun);
app.get('/api/user', (req, res) => {
//do something
});
app.post('/api/user', (req, res) => {
//do something
});
app.put('/api/user', (req, res) => {
//do something
});

How do I automatically return a 404 when a GET path doesn't exist?

I am using NodeJS, Express and Handlebars (template engine) to build a web application. Currently I'm trying to automatically redirect users whenever they enter an URL that does not exist (or whenever they might not have access to it).
The following returns the index page:
router.get('/', (req, res) => {
res.render('index/index');
});
But how do I make something like this:
router.get('/:ThisCouldBeAnything', (req, res) => {
res.render('errors/404');
});
The following example is from Github:
Say that I enter this URL:
https://github.com/thispagedoesnotexist
It automatically returns a 404. How do I implement this in my application?
Thanks in advance.
Use a middleware just after all route handlers to catch non existing routes:
app.get('/some/route', function (req, res) {
...
});
app.post('/some/other/route', function (req, res) {
...
});
...
// middleware to catch non-existing routes
app.use( function(req, res, next) {
// you can do what ever you want here
// for example rendering a page with '404 Not Found'
res.status(404)
res.render('error', { error: 'Not Found'});
});
After all your other routes you can add:
app.get('*', (req, res) => {
res.render('errors/404');
});
Alternately, you can use a middleware function after all your other middleware and routes.
app.use((req, res) => {
res.render('errors/404');
});
So you might end up with something that looks like:
//body-parser, cookie-parser, and other middleware etc up here
//routes
app.get('/route1', (req, res) => {
res.render('route1');
});
app.get('/route2', (req, res) => {
res.render('route2');
});
//404 handling as absolute last thing
//You can use middleware
app.use((req, res) => {
res.render('errors/404');
});
//Or a catch-all route
app.get('*', (req, res) => {
res.render('errors/404');
});
I see that you have express tagged. All you have to do is include a default handler that includes
res.status(404).render('404template')
For example
app.get('*', (req, res,next) => {
res.status(404).render('error.ejs')
});

Still wondering how to get Express to ignore matching route

I have this verbatim:
router.get('/top_level_questions,', function (req, res) {
res.json({success:true});
});
router.get('/:id', function (req, res) {
res.json({success:true});
});
what's happening is that a request to
/top_level_questions
will match the /:id handler. What is the official way to prevent that from happening>
The code:
router.get('/top_level_questions,', function (req, res) {
res.json({success:true});
});
Should be:
router.get('/top_level_questions', function (req, res) {
res.json({success:true});
});

Parenthesis in Node Express POST Route not found

I am mocking a POST route in Express for testing MS XRM.
Working Route:
http://localhost:3000/api/data/v8.0/something
app.post('/api/data/v8.0/something', function (req, res) {
res.send({data:'1234A'});
});
Failing Route:
http://localhost:3000/api/data/v8.0/something(ABC)/somethingelse
app.post('/api/data/v8.0/something(ABC)/somethingelse', function (req, res) {
res.send({data:'1234A'});
});
Parentheses in route paths have special meaning, but it looks like you can escape them like this:
app.post('/api/data/v8.0/something[(]ABC[)]/somethingelse', function (req, res) {
res.send({data:'1234A'});
});

Passing extra parameters to route handlers in Express

I'm relatively new to Express, and I'm looking for a way to make routes more reusable. In my app, I will have quite a few routes that can be passed to a generic handler, but will have different templates.
Example:
app.get('/about', function(req, res) {
res.render('about.html');
});
app.get('/', function(req, res) {
res.render('home.html');
});
While this example is contrite, I have 30+ such routes. What I would like to be able to do is something like this:
app.get('/about', generic.render('about.html'));
or otherwise somehow pass the template name to the function that returns res.render Is this possible in Express? All of my attempts to work around this result in variables being undefined.
I would prefer to not do something like this, tightly coupling my route parameters and template names:
app.get('/:template', function(req, res) {
res.render(req.params.template + '.html');
});
You could just make a a simple middleware that does this for you. Example:
function simpleRender(file, opts) {
opts || (opts = {});
return function(req, res) {
res.render(file, opts);
};
}
Then just use it like:
app.get('/about', simpleRender('about.html'));
app.get('/', simpleRender('home.html'));
This is how I do it:
const handler = (req, res, template) => {
res.render(template)
}
app.get('/about', (req, res) => {
handler(req, res, 'about.html')
})
This is a best practice for me
app.get('/:template',(req, res, next) => {
res.locals = `${template}.html`;
next();
},
renderMethod
);
function renderMethod(req, res){
res.render(res.locals)
}

Resources