Based on express documentation here we can attach HTTP method to express instance, and also execute callback function when the route matches.
We can also execute multiple callback route handlers. Route handlers can be in the form of a function, an array of functions, or combinations of both, as shown in the following examples.
app.get('/', function (req, res) {
res.send('GET request to the homepage');
});
or using array
var cb0 = function (req, res, next) {
console.log('CB0');
next();
}
var cb1 = function (req, res, next) {
console.log('CB1');
next();
}
var cb2 = function (req, res) {
res.send('Hello from C!');
}
app.get('/example/c', [cb0, cb1, cb2])
However,in our application i see the syntax developer has used is
app.get('/example/c',cb0, cb1)
Notice there is no array [] but 2 callback functions are passed as comma separated. This is working. But just curious how?
In Javascript you can pass any number of arguments into a function call no matter what the function definition is. For example function x(a, b){} could be called with more than two arguments. Programmers take advantage of the arguments special variable when they don't know in advance how many arguments a function call will receive. This is the case with the routing functions in express (.get, .put, .post, etc). They take any number of arguments you pass in and treat them as middleware functions as you can see in the documentation.
Its working due to middlewares. check this out
Related
can someone explain me why we are using this code in square brackets and why its assign to a const middlewares , Can we use it without const middlewares = [..]
const middlewares = [
layout(),
express.static(path.join(__dirname,'views')),
bodyParser.urlencoded({extended: false})
]
Sorry for the inconvenience, i am new to this field
This code creates an array of 3 elements.
In this case an array of 3 function pointers.
We can't know exactly why the code you are looking at would have it but my guess is there is a system somewhere that wants to use this array so you create the array.
const is used to indicate that it won't be changed.
You should read about closure in node in order to understand more about how this works.
The "square brackets" you mention are used to declare an Array literal.
const indicates that it's a constant and can't be changed once declared.
In this context (with your express tag), this array amalgamates several middlewares into a single structure to be applied at once, usually to a particular route. This is detailed in the official documentation on Using Express middleware:
Middleware can also be declared in an array for reusability.
This example shows an array with a middleware sub-stack that handles
GET requests to the /user/:id path
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
var logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, function (req, res, next) {
res.send('User Info')
})
app.use(function (req) {
if (myCondition(req)) {
express.static(`${__dirname}/REACT_APP_1`);
} else {
express.static(`${__dirname}/REACT_APP_2`);
}
});
Trying to serve different builds depending on the condition but it does not seems to be working as expected, I have already searched but nothing seems to be matching my condition, is there anything I'm doing wrong?
express.static() returns a middleware function. That middleware function has to get called while processing a specific route in order to actually do something useful. You were creating the middleware function, but never actually calling it so you never saw any results.
You could fix that like this:
// create our two express.static() middleware handlers
const handler1 = express.static(`${__dirname}/REACT_APP_1`);
const handler2 = express.static(`${__dirname}/REACT_APP_2`);
app.use(function (req, res, next) {
if (myCondition(req)) {
handler1(req, res, next);
} else {
handler2(req, res, next);
}
});
Note, I pulled the creation of the two express.static() handlers out of the app.use() body because there is no need to create them over and over inside of app.use(). You can create each of them once and then just use the appropriate one according to your conditional by calling it and passing it the (req, res, next) arguments for the current request.
I am newbie in ExpressJs and I do not clear about return statement of middleware. Please see below code :-
middleware.js
exports.checkPrivilege = (stateName, forPrivilege) => {
return (req, res, next) => { // THIS LINE MAKE CONFUSE, i.e, req, res and next
}
}
module.js
.....
.....
router.post('/create', checkPrivilege('module', 'write'), (req, res, next) => {
});
This means that checkPrivilege() is a function that, when called returns another function. In this case, it returns a function that is of the right format to use as a middleware handler.
So, when checkPrivilege(x,y) is called, it returns another function (that has not been executed yet) that can then be used as middleware.
So, when you see this:
router.post('/create', checkPrivilege('module', 'write'), (req, res, next) => {
// code here
next();
});
This does the following steps:
Creates a POST route handler for the /create route.
Calls checkPrivilege('module', 'write') immediately and as the return value it gets back another function that becomes a middleware handler for the /create route.
Then defines an inline anonymous route handler function for the /create route that will run after the middleware handler is done.
For a bit of clarity, it could also be written:
// create middleware function
let checkPrivilegeMiddleware1 = checkPrivilege('module', 'write');
// create route handler with middleware
router.post('/create', checkPrivilegeMiddleware1, (req, res, next) => {
// code here
next();
});
The typical reason it's done this way is that it is an easy way to make some parameters stateName and forPrivilege available to the middleware without creating another inline function body. This way the checkPrivilege() function can be used in multiple places within your code, each with their own stateName and forPrivilege settings - thus more reusable.
How to add middleware functions to each of expressjs route functions ? Most of route functions which turn out to be CRUD on database have standard before and after statements - is there a way to have before and after for route functions.
app.route('/api/resources').all(projectsPolicy.isAllowed)
.get(resources.list)
.post(resources.create);
I think it's possible to make this:
app.route('/api/resources').all(projectsPolicy.isAllowed)
.get(before,resources.list,after)
.post(before,resources.create,after);
where before and after are functions
Express supports multiple callbacks, as in
app.get('/example/b', function (req, res, next) {
// do something here, like modify req or res, and then go on
next();
}, function (req, res) {
// get modified values here
});
which could also be written as
app.route('/api/resources', projectsPolicy.isAllowed).get(...
assuming the middlewares isAllowed() function calls next() etc.
I see a lot of use next in node.js.
What is it, where does it come from? What does it do? Can I use it client side?
Sorry it's used for example here:
http://dailyjs.com/2010/12/06/node-tutorial-5/
look for the loadUser function.
This appears to be a variable naming convention in Node.js control-flow code, where a reference to the next function to execute is given to a callback for it to kick-off when it's done.
See, for example, the code samples here:
http://blog.mixu.net/2011/02/02/essential-node-js-patterns-and-snippets/
Let's look at the example you posted:
function loadUser(req, res, next) {
if (req.session.user_id) {
User.findById(req.session.user_id, function(user) {
if (user) {
req.currentUser = user;
return next();
} else {
res.redirect('/sessions/new');
}
});
} else {
res.redirect('/sessions/new');
}
}
app.get('/documents.:format?', loadUser, function(req, res) {
// ...
});
The loadUser function expects a function in its third argument, which is bound to the name next. This is a normal function parameter. It holds a reference to the next action to perform and is called once loadUser is done (unless a user could not be found).
There's nothing special about the name next in this example; we could have named it anything.
It is naming convention used when passing callbacks in situations that require serial execution of actions, e.g. scan directory -> read file data -> do something with data. This is in preference to deeply nesting the callbacks. The first three sections of the following article on Tim Caswell's HowToNode blog give a good overview of this:
http://howtonode.org/control-flow
Also see the Sequential Actions section of the second part of that posting:
http://howtonode.org/control-flow-part-ii
It's basically like a callback that express.js use after a certain part of the code is executed and done, you can use it to make sure that part of code is done and what you wanna do next thing, but always be mindful you only can do one res.send in your each REST block...
So you can do something like this as a simple next() example:
app.get("/", (req, res, next) => {
console.log("req:", req, "res:", res);
res.send(["data": "whatever"]);
next();
},(req, res) =>
console.log("it's all done!");
);
It's also very useful when you'd like to have a middleware in your app...
To load the middleware function, call app.use(), specifying the
middleware function. For example, the following code loads the
myLogger middleware function before the route to the root path (/).
var express = require('express');
var app = express();
var myLogger = function (req, res, next) {
console.log('LOGGED');
next();
}
app.use(myLogger);
app.get('/', function (req, res) {
res.send('Hello World!');
})
app.listen(3000);