I have a Node Express web project using Pug views.
By using the Response.locals object, I can make the Express Request object (req in my code) available to every pug file:
const app = require("express")();
app.use((req, res, next) => {
res.locals.req = req;
next();
});
Are there any side effects of using this approach and what are the disadvantages?
The convenience I get is that any view file can have access to all properties of the Request object, eg the query string, etc, without having to pass them explicitly using the textbook method like:
app.get("/xx", (req, res) => {
res.render("xx", { query: req.query });
});
Are there any side effects of using this and what are the disadvantages? Does it use up a lot of memory?
There are no side effects of using a template engine with express. Actually you can use res.render instead.
The convenience I get is that view files can have access to the query string,
If we know req.query has what we need that leaves the question is How to resolve the template for each route?
We will need to split the solution into two parts.
Part One - Genital request handle.
Although the response is dynamic the request resolving is known. Let say we have an additional parameter on the req object req.template and as we sad req.query is available as well.
The below function will render the req.query into req.template and send the response.
function pugTemplateHandler(req, res) {
const compiledFunction = pug.compileFile(req.template);
res.send(compiledFunction(req.query));
}
We don't care about Method nor Routes here. We expect that req to be set before this is called.
Part Two - Resolve the template file according to the route and method
Above we promised pugTemplateHandler that req will be ready for it. We can use Middleware to set the members we need on the req object.
app.get('...', (req, res, next) => {
req.template = 'PUG_TEAMPLATE_PAT'; // resolve template
// req.query = { ... }; // add or overwrite use params
next();
}, pugTemplateHandler); // pass modified req
app.post('...', (req, res, next) => { ... }, pugTemplateHandler);
app.put('...', (req, res, next) => { ... }, pugTemplateHandler);
app.del('...', (req, res, next) => { ... }, pugTemplateHandler);
Because we know the HTTP Method and the Route resolving the template is easy. Most likely here the template will be a static string.
The solution is extendable and has respect the idea of separation of concerns.
I have a MEAN stack application and using Node.js and Express.js as back-end API.
Assuming I have a 'comments' route as follow
/* GET /comments listing. */
router.get("/", function(req, res, next) {
Comment.find(function(err, comments) {
if (err) return next(err);
res.json(comments);
});
});
And use it in my server like this:
var commentsRouter = require('./routes/comments');
...
app.use('/comments', commentsRouter);
My question is: Is there a way to prevent users to access http://mrUrl/comments in browser and deny the request with probably 403 Forbidden message but at the same time JavaScript file tries to access the same URL will receive a content message (in the example should be res.json(comments);)
Also, would it be possible to enable such a restriction for all routes once, not for each.
Yes, you can use a middleware.
A middleware is a function you can pass before or after the main function you are executing (in this case, GET comments)
the order of the function location matters, what comes first - executes first, and you implement it like so:
app.use(myBrowsingRestrictionMiddlewareFunction) // Runs
app.use('/comments', commentsRouter);
app.use('/account', accountRouter);
You can also use within a route handler:
app.post('/comments', myMakeSureDataIsAlrightFunction, myMainCreateCommentFunction, myAfterStatusWasSentToClientAndIWishToMakeAnotherInternalActionMiddleware);
The properties req, res, next are passed into the function automatically.
which means, myBrowsingRestrictionMiddlewareFunction receives them and you can use them like so:
export function myBrowsingRestrictionMiddlewareFunction(req, res, next) {
if (req.headers['my-special-header']) {
// custom header exists, then call next() to pass to the next function
next();
} else {
res.sendStatus(403);
}
}
EDIT
Expanding regards to where to place the middleware in the FS structure (personal suggestion):
What I like to do is to separate the router from app.js like so:
app.js
app.use('/', mainRouter);
router.js
const router = express.Router();
router.use(middlewareForAllRoutes);
router.use('/comments', commentsRouter);
router.use(middlewareForOnlyAnyRouteBelow);
router.use('/account', accountRouter);
router.use(middlewareThatWillBeFiredLast); // To activate this, remember to call next(); on the last function handler in your route.
commentsRouter.js
const router = express.Router();
router.use(middlewareForAllRoutesONLYFORWithinAccountRoute);
route.get('/', middlewareOnlyForGETAccountRoute, getAccountFunction);
router.post('/', createAccount);
Tangential to this question, I would like to find out if there is a way of triggering the Express Router without actually going through HTTP?
The Router has a "private" method named handle that accepts a request, a response, and a callback. You can take a look at the tests that Express has for its Router. One example is:
it('should support .use of other routers', function(done){
var router = new Router();
var another = new Router();
another.get('/bar', function(req, res){
res.end();
});
router.use('/foo', another);
router.handle({ url: '/foo/bar', method: 'GET' }, { end: done });
});
The Express team uses SuperTest to perform integration tests on the Router. It is my understanding that SuperTest still uses the network but they handle all of this for you so it behaves as if the tests were all in memory. SuperTest does seem to be widely used and an acceptable way to test your routes.
As an aside, you didn't say what you were attempting to test but if your goal is to test some routes, an alternative to SuperTest could be to extract the logic in your routes into a separate module that can be tested independent of Express.
change:
routes
|
-- index.js
to:
routes
|
-- index.js
|
controllers
|
-- myCustomController.js
The tests could then simply target myCustomController.js and inject any necessary dependencies.
By going to the source of Express, I was able to find out that there is indeed an API that is just as simple as I wished for. It is documented in the tests for express.Router.
/**
* #param {express.Router} router
*/
function dispatchToRouter(router, url, callback) {
var request = {
url : url,
method : 'GET'
};
// stub a Response object with a (relevant) subset of the needed
// methods, such as .json(), .status(), .send(), .end(), ...
var response = {
json : function(results) {
callback(results);
}
};
router.handle(request, response, function(err) {
console.log('These errors happened during processing: ', err);
});
}
But ... the downside is, exactly the reason why it is undocumented in the first place: it is a private function of Router.prototype:
/**
* Dispatch a req, res into the router.
* #private
*/
proto.handle = function handle(req, res, out) {
var self = this;
...
}
So relying on this code is not the safest thing in the world.
You can use run-middleware module exactly for that. You create an express app a usuaul, and then you can call the app using your parameters
it('should support .use of other routers', function(done){
var app=require('express')()
app.get('/bar', function(req, res){
res.status(200).end();
});
app.runMiddleware('/bar',{options},function(responseCode,body,headers){
console.log(responseCode) // Should return 200
done()
})
});
More info:
Module page in Github & NPM;
Examples of use run-middleware module
Disclosure: I am the maintainer & first developer of this module.
I'm using MEAN stack with MeanJs. The thing is, I have a task that requires calling a GET request from the server side (Expressjs) to another server (with a different domain name).
The code in the client side (AngularJs) calls:
$scope.getWorkflow = function() {
$http.get('/ezee', $scope.credentials).success(function(response) {
console.log(response.message);
}).error(function(response) {
console.log('error');
});
};
And the corresponding server controller function is:
exports.list = function(req, res) {
req.get('http://ezslave.io', function(q, r){
res.json({message: r.message}); // just to test
});
};
Obviously, the code below doesn't work. I'm unsure about how to make a GET request from that list function. Am I supposed to use ExpressJs or pure NodeJs for this? And how to get the correct library loaded?
Use the request module of nodejs : https://github.com/mikeal/request
for sending the http request.
var request = require("request");
exports.list = function(req, res) {
request("http://ezslave.io",function(err,response,body){
res.send(response);
});
};
Hope this helps you
Almost every Express app I see has an app.use statement for middleware but I haven't found a clear, concise explanation of what middleware actually is and what the app.use statement is doing. Even the express docs themselves are a bit vague on this. Can you explain these concepts for me please?
middleware
I'm halfway through separating the concept of middleware in a new project.
Middleware allows you to define a stack of actions that you should flow through. Express servers themselves are a stack of middlewares.
// express
var app = express();
// middleware
var stack = middleware();
Then you can add layers to the middleware stack by calling .use
// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
next();
});
A layer in the middleware stack is a function, which takes n parameters (2 for express, req & res) and a next function.
Middleware expects the layer to do some computation, augment the parameters and then call next.
A stack doesn't do anything unless you handle it. Express will handle the stack every time an incoming HTTP request is caught on the server. With middleware you handle the stack manually.
// express, you need to do nothing
// middleware
stack.handle(someData);
A more complete example :
var middleware = require("../src/middleware.js");
var stack = middleware(function(data, next) {
data.foo = data.data*2;
next();
}, function(data, next) {
setTimeout(function() {
data.async = true;
next();
}, 100)
}, function(data) {
console.log(data);
});
stack.handle({
"data": 42
})
In express terms you just define a stack of operations you want express to handle for every incoming HTTP request.
In terms of express (rather than connect) you have global middleware and route specific middleware. This means you can attach a middleware stack to every incoming HTTP requests or only attach it to HTTP requests that interact with a certain route.
Advanced examples of express & middleware :
// middleware
var stack = middleware(function(req, res, next) {
users.getAll(function(err, users) {
if (err) next(err);
req.users = users;
next();
});
}, function(req, res, next) {
posts.getAll(function(err, posts) {
if (err) next(err);
req.posts = posts;
next();
})
}, function(req, res, next) {
req.posts.forEach(function(post) {
post.user = req.users[post.userId];
});
res.render("blog/posts", {
"posts": req.posts
});
});
var app = express.createServer();
app.get("/posts", function(req, res) {
stack.handle(req, res);
});
// express
var app = express.createServer();
app.get("/posts", [
function(req, res, next) {
users.getAll(function(err, users) {
if (err) next(err);
req.users = users;
next();
});
}, function(req, res, next) {
posts.getAll(function(err, posts) {
if (err) next(err);
req.posts = posts;
next();
})
}, function(req, res, next) {
req.posts.forEach(function(post) {
post.user = req.users[post.userId];
});
res.render("blog/posts", {
"posts": req.posts
});
}
], function(req, res) {
stack.handle(req, res);
});
After simplifying things, a web server can be seen as a function that takes in a request and outputs a response. So if you view a web server as a function, you could organize it into several pieces and separate them into smaller functions so that the composition of them will be the original function.
Middlewares are the smaller functions that you can compose with others and the obvious benefit is that you can reuse them.
I add a late answer to add something not mentioned in the previous answers.
By now it should be clear that middleware is/are function(s) run between the client request and the server answer. The most common middleware functionality needed are error managing, database interaction, getting info from static files or other resources. To move on the middleware stack the next callback must be called, you can see it in the end of middleware function to move to the next step in the flow.
You can use the app.use approach and have a flow like this:
var express = require('express'),
app = express.createServer(),
port = 1337;
function middleHandler(req, res, next) {
console.log("execute middle ware");
next();
}
app.use(function (req, res, next) {
console.log("first middle ware");
next();
});
app.use(function (req, res, next) {
console.log("second middle ware");
next();
});
app.get('/', middleHandler, function (req, res) {
console.log("end middleware function");
res.send("page render finished");
});
app.listen(port);
console.log('start server');
but you can also use another approach and pass each middleware as function arguments. Here is a example from the MooTools Nodejs website where midleware gets the Twitter, Github and Blog flow before the response is sent back to the client. Note how the functions are passed as arguments in app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. Using app.get will only be called for GET requests, app.use will be called for all requests.
// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
blogData.get(function(err, blog) {
if (err) next(err);
res.locals.lastBlogPost = blog.posts[0];
next();
});
}
// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
res.render('index', {
title: 'MooTools',
site: 'mootools',
lastBlogPost: res.locals.lastBlogPost,
tweetFeed: res.locals.twitter
});
});
expressjs guide has pretty neat answer to your question, I highly recommend you to read that, I am posting a short snippet of the guide, the guide is quite good.
Writing middleware for use in Express apps
Overview
Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.
Middleware functions can perform the following tasks:
Execute any code.
Make changes to the request and the response objects.
End the request-response cycle.
Call the next middleware in the stack.
If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.
Example
Here is an example of a simple “Hello World” Express application. The remainder of this article will define and add two middleware functions to the application: one called myLogger that prints a simple log message and another called requestTime1 that displays the timestamp of the HTTP request.
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
Middleware function myLogger
Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it. The middleware function is assigned to a variable named myLogger.
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.
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)
Every time the app receives a request, it prints the message “LOGGED” to the terminal.
The order of middleware loading is important: middleware functions that are loaded first are also executed first.
If myLogger is loaded after the route to the root path, the request never reaches it and the app doesn’t print “LOGGED”, because the route handler of the root path terminates the request-response cycle.
The middleware function myLogger simply prints a message, then passes on the request to the next middleware function in the stack by calling the next() function.
This post will only contain myLogger middleware, for further post you could go to the original expressjs guide here.
=====Very very simple explanation=====
Middlewares are often used in the context of Express.js framework and are a fundamental concept for node.js . In a nutshell, Its basically a function that has access to the request and response objects of your application. The way I'd like to think about it, is a series of 'checks/pre-screens' that the request goes through before the it is handled by the application. For e.g, Middlewares would be a good fit to determine if the request is authenticated before it proceeds to the application and return the login page if the request is not authenticated or for logging each request. A lot of third-party middlewares are available that enables a variety of functionality.
Simple Middleware example:
var app = express();
app.use(function(req,res,next)){
console.log("Request URL - "req.url);
next();
}
The above code would be executed for each request that comes in and would log the request url, the next() method essentially allows the program to continue. If the next() function is not invoked, the program would not proceed further and would halt at the execution of the middleware.
A couple of Middleware Gotchas:
The order of middlewares in your application matters, as the request would go through each one in a sequential order.
Forgetting to call the next() method in your middleware function can halt the processing of your request.
Any change the req and res objects in the middleware function, would make the change available to other parts of the application that uses req and res
Middlewares are functions executed in the middle after the input/source then produces an output which could be the final output or could be used by the next middleware until the cycle is complete.
It is like a product that goes through an assembly line where it gets modified as it moves along until it gets completed, evaluated or gets rejected.
A middleware expects some value to work on (i.e. parameter values) and based on some logic the middleware will call or not call the next middleware or send a response back to the client.
If you can't still grasp the middleware concept, it is in a way similar to the Decorator or Chain of command patterns.
Middleware is a subset of chained functions called by the Express js routing layer before the user-defined handler is invoked. Middleware functions have full access to the request and response objects and can modify either of them.
The middleware chain is always called in the exact order in which it has been defined, so it is vital for you to know exactly what a specific piece of middleware is doing. Once a middleware function finishes, it calls the next function in the chain by invoking its next argument as function. After the complete chain gets executed,the user request handler is called.
Keep things simple, man!
Note: the answer is related to the ExpressJS builtin middlware cases, however there are different definitions and use cases of middlewares.
From my point of view, middleware acts as utility or helper functions but its activation and use is fully optional by using the app.use('path', /* define or use builtin middleware */) which don't wants from us to write some code for doing very common tasks which are needed for each HTTP request of our client like processing cookies, CSRF tokens and ..., which are very common in most applications so middleware can help us do these all for each HTTP request of our client in some stack, sequence or order of operations then provide the result of the process as a single unit of client request.
Example:
Accepting clients requests and providing back responses to them according to their requests is the nature of web server technology.
Imagine if we are providing a response with just "Hello, world!" text for a GET HTTP request to our webserver's root URI is very simple scenario and don't needs anything else, but instead if we are checking the currently logged-in user and then responding with "Hello, Username!" needs something more than usual in this case we need a middleware to process all the client request metadata and provide us the identification info grabbed from the client request then according to that info we can uniquely identify our current user and it is possible to response to him/her with some related data.
Hope it to help someone!
In very basic term if i want to explain it like this i learn this from traversymedia youtube channel express crash course.
ok so middle ware is a function who execute after you make a call to your route like this.
var logger = function(req, res, next){
console.log('logging...');
next();
}
app.use(logger);
This logger function execute every time you refresh your page that means you can write anything in it that you required to do after your page get rendered any operation api call, reset things basically anything. and put this middleware before your route function order of middleware is really important or it dons't work