node express.Router().route() vs express.route() - node.js

What should I use:
express.Router().route()
or
express.route()
?
Is it true express.Router().route() is someway deprecated?

For the current version of Express, you should use express.Router().route(). See the express documentation for confirmation. express.Router().route() is not depreciated.
For example:
var router = express.Router();
router.param('user_id', function(req, res, next, id) {
// sample user, would actually fetch from DB, etc...
req.user = {
id: id,
name: 'TJ'
};
next();
});
router.route('/users/:user_id')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
next();
})
.get(function(req, res, next) {
res.json(req.user);
})
.put(function(req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name;
// save user ... etc
res.json(req.user);
})
.post(function(req, res, next) {
next(new Error('not implemented'));
})
.delete(function(req, res, next) {
next(new Error('not implemented'));
})

Router.route() can use for chainable routes.
Meaning: You have one API for all the METHODS, you can write that in .route().
var app = express.Router();
app.route('/test')
.get(function (req, res) {
//code
})
.post(function (req, res) {
//code
})
.put(function (req, res) {
//code
})

Related

Is it possible to dynamically use a route part to call passport strategy?

Currently, I have the following code for many more oath provider:
// facebook
router.get("/facebook", passport.authenticate("facebook", { scope: ["email"] }));
router.get("/facebook/callback", passport.authenticate("facebook"), (req, res) => {
console.log(chalk.blue("went into facebook callback"));
res.redirect("http://localhost:3000/profile");
});
// github
router.get("/github", passport.authenticate("github"));
router.get("/github/callback", passport.authenticate("github"), (req, res) => {
console.log(chalk.blue("went into github callback"));
res.redirect("http://localhost:3000/profile");
});
Is there a way to unify that into an abstracted route? I.e. something like
// github
router.get("/:provider", passport.authenticate(:provider));
router.get("/:provider/callback", passport.authenticate(:provider), (req, res) => {
console.log(chalk.blue("went into {:provider} callback"));
res.redirect("http://localhost:3000/profile");
});
Update:
The following piece of code does what I want. Thx to #Usman Abdur Rehman.
function callbackDistributer(req, res, next) {
console.log(req.params);
global.provider = req.params.provider;
next();
}
router.get(
"/:provider/callback",
callbackDistributer,
(req, res, next) => {
passport.authenticate(global.provider)(req, res, next);
},
(req, res) => {
console.log(chalk.red("went into: " + global.provider));
res.redirect("http://localhost:3000/profile");
}
);
Have a middleware function going before the passport.authenticate middleware
function ownMiddleware(req,res,next){
global.provider = req.params.provider
next()
}
and then use it in the route handler as
router.get("/:provider/callback", ownMiddleware ,passport.authenticate(global.provider), (req, res) => {
console.log(chalk.blue("went into {:provider} callback"));
res.redirect("http://localhost:3000/profile");
});
I think it should work

Express router bypasses middleware

I am trying to create middleware to handle the response that are next()ed from the routes, but it bypasses route.use and throws 404
const router = require('express').Router();
const { errorResponse, successResponse, redirectResponse } = require('./test');
const errorResponse = (err, req, res, next) => {
next(Boom.notFound());
};
const successResponse = (err, req, res, next) => {
res.locals.res = {
data: {
hello: 'world'
}
};
next();
};
const redirectResponse = (err, req, res, next) => {
res.locals.res = {
meta: {
redirect: true
}
};
next();
};
module.exports = (app) => {
/**
* Test Routes
*/
router.get('/successTest', successResponse);
router.get('/errorTest', errorResponse);
router.get('/redirectTest', redirectResponse);
router
.use((err, req, res, next) => {
console.log('successHandler');
next();
})
.use((err, req, res, next) => {
console.log('redirectHandler');
next();
})
.use((err, req, res, next) => {
console.log('errorHandler');
res.status(200).json({});
});
// does not go to any of the middlewares and gives out 404
// from digging in i found that err param is not err but is req
app.use('/v1', router);
};
Thanks for helping
Take a look at Express.js Error-handling middleware documentation.
Basically it says that middleware with 4 arguments like
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
interpreted as middleware to handle errors.
It means that it won't act like regular middleware.
For example:
app.get('/1',
(err, req, res, next) => {
// will not be outputted in console
console.log('got here');
next();
},
(req, res) => {
res.send('Hello World!');
});
app.get('/2',
(req, res, next) => {
console.log('got here');
next();
},
(req, res) => {
res.send('Hello World!');
});

mongoose: how to search mongoDB with mongoose

I am learning Express.js, MongoDB and Mongoose, and i am creating a small app that lets me store items to a list.
I am trying to Create a GET /list/search route which allows to search for items in the list, but i haven't gotten it to work.
Here is my code
Routes
const express = require('express');
router = express.Router();
const db = require("../models");
router.get('/', function(req, res, next){
db.List.find().then(function(list){
res.render('index', {list});
});
});
router.get('/new', function(req, res, next){
res.render('new');
});
router.get('/:id', function(req, res, next){
db.List.findById(req.params.id).then(function(list){
res.render('show', {list});
});
});
router.get('/:id/edit', function(req, res, next){
db.List.findById(req.params.id).then(function(list){
res.render('edit', {list});
});
});
router.get('/search', function(req, res, next){
db.List.findOne(req.query.search).then(function(list){
console.log(list);
res.render('show', {list});
});
});
router.post('/', function(req, res, next){
db.List.create(req.body).then(function(list){
res.redirect('/');
});
});
router.patch('/:id', function(req, res, next){
db.List.findByIdAndUpdate(req.params.id, req.body).then(function(list){
res.redirect('/');
});
});
router.delete('/:id', function(req, res, next){
db.List.findByIdAndRemove(req.params.id).then(function(list){
res.redirect('/');
});
});
module.exports = router;
Index.pug
extends base.pug
block content
h1 My List
form(action="/list/search" method="GET")
input(type="text" name="search")
input(type="submit", value="search")
a(href="/list/new") Add New Item!
each item in list
p ITEM: #{item.name} QUANTITY: #{item.quantity}
a(href=`/list/${item.id}/edit`) Edit
my main problem is the GET /search, i want to pass in a search query to the search box and return the result to the render file
router.get('/search', function(req, res, next){
db.List.findOne(req.query.search).then(function(list){
console.log(list);
res.render('show', {list});
});
});
Thanks in advance
You need to specify the parameters as attributes in the query. list will be null, if no matching record was found.
router.get('/search', function (req, res, next) {
db.List.findOne({
name: req.query.name,
age: req.query.age
}).then(function (list) {
console.log(list);
if (list === null) {
return res.render('show', {
list: []
});
}
return res.render('show', {
list: list
});
}).catch((err) => {
console.log('err', err);
return res.render('show', {
list: []
});
});
});

how to group api in express

Here is the example:
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
//code
});
app.post('/user/register', function(req, res) {
//code
})
app.put('/user/register', validateToken, function(req, res) {
//code
})
app.delete('/user/delete', validateToken, function(req, res) {
//code
})
If I have 10 api that need validToken, I should add validToken middleware 10 times, like:
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
....
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
How can I group api by using the same middleware?
Here's how to re-use the same callback function for multiple routes (like middleware):
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
// code
});
app.post('/user/register', function(req, res) {
// code
});
// Be sure to specify the 'next' object when using more than one callback function.
app.put('/user/register', validateToken, function(req, res, next) {
// code
next();
});
app.delete('/user/delete', validateToken, function(req, res, next) {
// code
next();
});
Also, you can replace app.METHOD (e.g. .post, .get, .put, etc.) with app.all and your callback will be executed for any request type.
Just wrong, so do not put into mass participation of the (Google translated from: 刚才看错了,改成这样就不用放进传参了)
var group = {url:true,url:true,url:true};
app.use(function(req,res,next){
if(group[req.url]){
// Do something with request here
next();
} else {
next();
}
})

How to pass data during a res.redirect?

My view relies on some data to render, like this:
router.get("/", (req, res) => {
res.render(
'index', {
data: layout_data,
user: req.user
}
);
});
router.post('/login', passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
It works. But when I added the csurf middleware like
router.post('/login', parseForm, csrfProtection, passport.authenticate('local'), function(req, res) {
res.redirect('/');
});
The layout engine tells me that data is undefined. I suspect that the csurf middleware erases the data.
I tried to fix it like this:
router.get("/", (req, res) => {
req.mydata = {};
req.mydata.layout_data = layout_data;
res.render(
'index', {
data: req.mydata.layout_data,
user: req.user
}
);
});
router.post('/login', parseForm, csrfProtection, passport.authenticate('local'), function(req, res) {
if (!req.mydata) {
req.mydata = {};
}
req.mydata.layout_data = layout_data;
res.redirect('/');
});
It still does not work. The data is still undefined.
What is the best practice to resolve this problem?
My guess is: your layout_data is undefined.

Resources