When to use () in a middleware and when to use just reference - express

var cookieParser = require('cookie-parser')
var cookieValidator = require('./cookieValidator')
var app = express()
async function validateCookies (req, res, next) {
await cookieValidator(req.cookies)
next()
}
app.use(cookieParser())
app.use(validateCookies)
// error handler
app.use(function (err, req, res, next) {
res.status(400).send(err.message)
})
app.listen(3000)
In the above code both cookieParser() and validateCookies are middlewares but the way of executing them are different. There is a function like () with cookieParser but not with validateCookies. Can someone please explain why? Sorry If I am sounding foolish.

The app.use() function takes a single parameter, which is a function reference for a function that serves as a middleware for your router in Express.
You’ve correctly included the reference to your validateCookies function without parenthesis, as you just want Express to know which function you’d like it to use as middleware, and not to execute it at the time (Express will invoke the function for you when it’s time).
cookie-parser is a bit of an outlier (and I can see from where your confusion stems). The cookieParser() function actually returns a function reference upon successful execution. This design is likely because this particular module allows developers to pass in certain values to change the resulting function’s behavior as a middleware.

Related

how do i refactor middlewares routes in express?

I have a question. Following this code:
const express = require('express');
const usersRouter = require('./routes/users');
const carsRouter = require('./routes/cars');
const app = express();
app.use(express.json());
app.use('/users', usersRouter);
app.use('/cars', carsRouter);
//and other app use routes
module.exports = app;
the question is about app.use routes, imagine having 50, 100, 1000 of routes, it isnt a best practise to update app.js everytime! how to refactor it the right way?
There are two possible cases:
there are actually 50, 100, 1000 different functions (or routers) that corresponds that many routes. In this case, you need to organize them in some neat way. I suggest scanning folders and calling app.use them in a cycle.
there aren't so many different functions, but instead there are copy/paste code or maybe some few routes correspond to one function. This means you can either organize that functions in an array and then, make app.use inside of a loop. Or, maybe you can create generic muddleware that analyzes path and calls proper function to deal with the request:
app.use(function(req, res, next) {
if (req.path.match(/.../)) {
return ...
}
if (req.path.match(/.../)) {
return ...
}
...
// if nothing matches, run the next middleware
next();
});

Why does the use() method still executed after get() has handled a request successfully in express.js?

I have this express.js code:
app.get('/', (req, res) => {
res.render('homePage', { title: 'Express' });
});
app.use((req, res) => {
console.log('use() is executed');
res.end();
});
If the request is handled by the get() method, use() is not supposed to execute. But I noticed that it still execute even though everything was fine and the page is rendered. Did I do something wrong or did I miss something? Thanks.
From Express Doc:
Link: http://expressjs.com/en/4x/api.html#app.use
app.use([path,] callback [, callback...])
Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches the path.
app.use() register the function as middleware, and you didn't specify the path. That's why it will run every time when any route is called.
The placement of the middlewares will change the execution order. However, they don't change the fact that the middleware will be executed as, well middlewares, which will be executed before the actual functions with in the routes.

Needed explanation on Express MiddleWares with next

I have only one MiddleWare with next called inside, and the request-response cycle is ended even though i did not use the res.send(), how is that?
app.use("/", function (req, res, next) {
console.log(`${req.method} ${req.path} - ${req.ip}`);
next();
});

Reference app in express middleware

Supposing we have some middleware in express 4.0:
app.use((req, res, next) => {
// ... i want app here. except this
// method is imported from another file
// so app isn't in scope.
});
Is there any way to get the app object?
I'm writing several custom middleware packages and I keep finding myself needing to reference app (from another file of course). I'm doing hokey things like this:
app.use(fabMiddleware(app));
Which is really a high-order function:
const fabMiddleware = (app) => {
return function(req, res, next) {
// ... now i can use app
}
}
modue.exports = fabMiddleware;
Does perhaps this, req or res have a reference to app?
Yes you can access the app instance without needing to explicitly pass it in. Simply call req.app or res.app to get access to it.
https://expressjs.com/en/4x/api.html#req.app
https://expressjs.com/en/4x/api.html#res.app

Is there a workaround for express 4.x route('/path') with params support?

I'm using a expressjs 4.x to build a simple api on top of mongodb.
The api needs to serve a few sets of data:
/api/v1/datatype1
/api/v1/datatype2
For each data type, I have CRUD operations (post, get, put, delete).
The api requests would look like this:
POST /api/v1/datatype1
GET /api/v1/datatype1:_id
PUT /api/v1/datatype1:_id
DELETE /api/v1/datatype1:_id
If I create a router params like this:
dataType1ApiRouter.param("entity_id", function (req, res, next, id) {
//async db fetch here by id, then call next with fetched data
//or error if faild request/not found entity.
//let's say req.dataEntity = dataEtity; next();
} );
If I create a route like this:
dataType1ApiRouter.route("/datatype1")
.get(":entity_id", function (req, res, next) {
//expcet req.dataEntity to be fetched by the param filter.
})
.post(function(req, res, next) {
//just create an new dataType1 entity.
});
I am getting a syntax error. The route .get and .post (and other methods like those) expect just one parameter, resulting in an error:
Route.get() requires callback functions but got a [object String]
Is there a way to actually group all the "/datatype1" requests under one url declaration instead of repeating the method("datatype1:entity_id") for each method that requires the ID expect for the post method?
There isn't a clean way to do this with Router.route(), but you might consider doing this with another Router instead of a Route there. Then, you could just mount that sub-router.
Basic example, modifying the code you provided:
var mainRouter = express.Router(),
subrouter = express.Router();
subrouter.param("entity_id", function (req, res, next, id) {
// param handler attached to subrouter
});
subrouter.post('/', function(req, res, next) {
// post handler attached to base mount-point
});
subrouter.get("/:entity_id", function (req, res, next) {
// get handler attached to base mount-point/<id>
});
// here we mount the sub-router at /datatype1 on the other router
mainRouter.use('/datatype1', subrouter);
Note that this requires adding a '/' to the URL, so instead of /api/v1/datatype1[someidhere] it would be /api/v1/datatype1/someidhere