How to terminate route middleware chain? - node.js

I have a simple Express router setup with authentication middleware. I have something like the code below.
If the user navigates to '/authenticate' with improper credentials, I want the middleware to send an error response and all middleware and route processing to cease. To do that, I sent a response, told Express to skip the rest of the route middleware with next('route'), and included a return to stop processing the authMiddleware function.
let router = express.Router()
function authMiddleware(req, res) {
//Do some authentication checks
if(!authenticated) {
res.status(403).send("Could not authenticate. :-(")
next('route')
return
}
//Additional authentication checks
}
router.use(authMiddleware)
router.post('/authenticate', (req, res)=> {
res.send("You should not see me if you aren't authenticated!")
}
I would expect the post route not to run; however, it does, giving me the error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. I have searched Google, Stack Overflow, and the Express docs to no avail, though perhaps my search terms are lacking.
I saw a Scotch article that suggested doing a redirect, but that seems a little hacky and inelegant.
So my question: What is the proper way to terminate a middleware/routing chain?

To terminate the middelware and route chain, simply do not calling the next().
function authMiddleware(req, res, next) {
let authenticated = false;
if(!authenticated) {
res.status(403).send("Could not authenticate. :-(");
// do not call next(), and simply return
return;
}
//Additional authentication checks
// all passed, let's pass it to next()
next();
}

Related

How to apply instance of use() to all routes except those handed by app.use(express.static("dist"))?

I think I have resolved this issue in the process of writing it, basically the solution seems to be:
Move the static file handler above the other instance of use()
Confirmation that this is an acceptable approach would be appreciated though and perhaps help others in a similar scenario.
Desired Behaviour
Apply a use() instance to all routes except those handled by:
app.use(express.static("dist"));
Actual Behaviour
use() is being applied to all routes, including those handled by:
app.use(express.static("dist"));
Scenario
For securing access to API's, I am using the model described in this Lynda.com tutorial:
Node.js: Securing RESTful APIs
In pseudo code, the model is essentially comprised of:
a global use() instance that checks if a jwt token has been sent
if a token has been sent, if verifies the token
it sets the req.user property to undefined if verification fails or a token wasn't sent
otherwise, it sets the req.user property to the decoded jwt value if verification succeeds
subsequent middleware performs conditional behaviour based on the value of req.user
This model is working well for all intents and purposes.
However, I recently added some console logging and can see that verification is being performed for both:
api requests (desired behaviour)
static files served via app.use(express.static("dist")) per this convention (undesired behaviour)
Question
How can I apply the verification use() instance to all routes, except those handled by app.use(express.static("dist")).
What I've Tried
I think I have resolved this issue by moving section 2 of the code below above section 1.
// 01. verification use() called on all requests
app.use((req, res, next) => {
// if jwt authorisation has been sent in headers, verify it
if (req.headers && req.headers.authorization && req.headers.authorization.split(' ')[0] === 'JWT') {
console.log("jwt verification sent, verifying...");
try {
// this is synchronous as it has no callback
req.user = jsonwebtoken.verify(req.headers.authorization.split(' ')[1], 'RESTFULAPIs');
console.log("jwt verified, will return decoded value");
} catch (err) {
req.user = undefined;
console.log("jwt verification failed, user will remain undefined: " + err);
}
// move to the next piece of middleware
next();
}
// if jwt authorisation has not been sent in headers
else {
console.log("jwt verification not sent, leaving user as undefined");
console.log(req.originalUrl);
req.user = undefined;
// move to the next piece of middleware
next();
}
});
// 02. use() for serving static files
app.use(express.static("dist"));
// 03. middleware to check if login has been verified
const api_login_required = (req, res, next) => {
// if token verification was successful and the user property exists
if (req.user) {
// move to the next piece of middleware
next();
}
// otherwise, return unauthorised user message
else {
res.json({ verification: 0 });
}
}
// 04. middleware called in route handlers
app.route("/api/:api_version/users/private_data")
.get(api_login_required, api_users_private_data_get)
.post(api_login_required, api_users_private_data_post);
Middleware always controls the flow from to button in which order they wrote. Like
if (example 1)code like
app.use((req,res, next)=>{// middleware 1; next()} )
app.get('/rot1', (req, res)=> res.status(200).send('route 1'));
app.get('/rot2', (req, res)=> res.status(200).send('route 2'));
In this case, middleware appears in both route1, route because of middleware set at the top of the route.
If (example 2)code like
app.use((req,res, next)=>{// middleware 1; next()} )
app.get('/rot1', (req, res)=> res.status(200).send('route 1'));
app.use((req,res, next)=>{// middleware 2; next()} )
app.get('/rot2', (req, res)=> res.status(200).send('route 2'));
Here middleware1 applied in both route1 and route 2
But middleware2 applied only on route2.
But you can also define specific middleware for each route
function middleware1(req, res, next){
next();
}
function middleware2(req, res, next){
next();
}
app.get('/rot1', middleware1, (req, res)=> res.status(200).send('route 1'));
app.get('/rot2', middleware2, (req, res)=> res.status(200).send('route 2'));
Here middleware1 only applied on route1 and middleware2 only applied on route2.
Maybe above explanation help you!!

Express.js middleware executing for a route defined above it

From what I have read here and here, the order in which you place your middleware function matters, as you can have certain routes not go through the middleware function if it is placed before the route, and the routes which are placed after will go through this middleware function.
I am seeing mixed results as my dev environment is not respecting this and my prod environment is. The code is exactly the same.
What I am trying to do is have my login route not be protected by a token checker middleware function and have the rest of my routes protected by a token.
Here is my code:
routes.get('/login', function(req, res) {
// login user, get token
});
routes.use(function(req, res, next) {
// check header or url parameters or post parameters for token
var token = req.headers['access-token'];
// decode token
if (token) {
// validate token
}
else if (req.method === 'OPTIONS') {
next();
}
else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
routes.get('/query/:keywords', function(req, res) {
console.log(req.params.keywords);
// execute query
});
app.use('/', routes);
the /query route is the only one that should have to go through the token middleware function correct? Right now I am getting the /login route also going through the token middleware function, which doesn't make sense as I shouldn't need to have a token to login.
Better yet, if there is a way to target which routes I want protected and which routes I do not want protected, this seems better than having to rely on an "order" of where the middleware function is placed.
First, follow along this usage in ExpressJS:
More than one callback function can handle a route (make sure you specify the next object). For example:
app.get('/example/b', function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from B!')
})
You'll notice it's definition is close to what you're declaring on routes.use(yourFunction(...)). However, there's no real reason to do it this way other than following examples you've seen in documentation, which is a good way to start nevertheless.
However, it's a flimsy implementation, express will allow hierarchies within it's .get() .post() methods, that's correct, but this is a use case specific and not what you're looking for.
What you need is to implement your custom auth process using the double callback configuration. do this:
// You can save this function in a separate file and import it with require() if you want
const tokenCheck = function(req, res, next) {
// check header or url parameters or post parameters for token
var token = req.headers['access-token'];
// decode token
if (token) {
// validate token
}
else if (req.method === 'OPTIONS') {
next();
}
else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
});
routes.get('/login', function(req, res) {
// login user, get token [Unprotected]
});
routes.get('/query/:keywords', tokenCheck, function(req, res) {
console.log(req.params.keywords);
// execute query [Protected with tokenCheck]
});
app.use('/', routes);
You might need to play around with the code above, but it'll guide you on the right direction, this way, you can specify particular routes to execute the tokenCheck(req, res, next) function as you want.
The easiest way to do this is to use Router Middleware to scope Routes that require Authentication and the routes that don't. Since all Routers are Middleware, we can implement them just like any other middleware. Ensuring that we place the Routers and Routes in the order that we would like our Routes to be evaluated.
In the below example, the Express server has 2 routers, a LoginRouter and an ApiRouter.
LoginRouter - Generates a Token when receiving a request to POST /login and returns that to the requester for subsequent use in the /api routes.
ApiRouter - Wraps all other routers, centralizes middleware that needs to be globally applied to all routes under /api. Is only accessible to Authenticated Requests.
The API Router is only accessible if there is a token included in the Header and that token is obtained from the LoginRouter. LoginRouter has no authentication required.
With this setup, you'll keep adding routers after the Authorization Middleware to the API Router via .use() on the ApiRouter.
The below pattern of composing Routers from other Routers is very powerful, scalable and easy to maintain.
server.js
const express = require('express')
const bodyParser = require('bodyParser')
const ApiRouter = require('./routes/api')
const LoginRouter = require('./routes/login')
const port = process.env.PORT || 1337
const server = express()
server.use(bodyParser.json())
server.use('/login', LoginRouter)
server.use('/api', ApiRouter)
server.listen(port, () => console.log(`Listening on ${port}`))
LoginRouter - /routes/login.js
const router = require('express').Router()
router.post('/', (req, res) => {
// Validate Credentials
// some validation code...
// Then create the token for use later in our API
let token = '...'
// Response 200 OK with the token in the message body
return res.status(200).send({token})
})
module.exports = router
ApiRouter - /routes/api/index.js
const router = require('express').Router()
const UsersRouter = require('./routes/api/users')
router.use((req, res, next) => {
let authorizationHeader = req.headers['authorization'] || req.headers['Authorization'] // handle lowercase
let [, token] = authorizationHeader.split(' ')
if (!token) {
return res.sendStatus(403) // Forbidden, you're not logged in
} else {
// validate the token
if (!tokenIsValid) {
return res.sendStatus(403) // Forbidden, invalid token
}
// Everything is good, continue to the next middleware
return next()
}
})
router.use('/users', UsersRouter)
module.exports = router
UsersRouter - /routes/api/users
const router = require('express').Router()
router.get('/', (req, res) => {
// We only get here if the user is logged in
return res.status(200).json({users: []})
})
module.exports = router
The application of the token middleware should not happen to the login route due to route order and the fact the login route never calls the next object. Without more information we really can't trouble shoot what is happening beyond that however you could try inspecting it in your dev environment with a debugger break and looking at the req that hits that middleware.
We can however give you some information on how to try and isolate your .use middleware and how application of middleware order applies so that you can try and separate it from the login route entirely like in the bottom of your question.
When applying middleware to only specific routes you should keep note that order and .use are for middleware that should answer the request before telling express to continue looking for other middleware that come after them in the router that will also handle the request. If you only want it on a few routes, you can add it to only a few routes by being explicit like so:
router.get('/route', [ middleware1, middleware2, ..., middlewareX])
or
router.get('/route', middleware1, middleware2, ..., middlewareX)
both patterns will work. I however find the array pattern a little more palatable since I can define a lot of middle wares I want to apply and then concatenate new middleware for specific logic, and I only need modify where I declare that concatenation to add more functionality. It'd however rare to need that many middleware and you should be able to use either.
You could also section that middleware off to a subset of routes by using a router and applying it as the first middleware to the route chain before the router.
app.use('/user', authentication, userRouter)
or you can put it inside the router as the first middleware with a .use so that it handles all requests.
So remember the general tips about middleware usage:
order matters for middleware application
optional middleware that should be applied on route basis should be applied with the other middleware in order for only that route
error handling middleware must always come last, and have four arguments (err, req, res, next)
use routers to section .use middleware to specific routes and sets of routes
You can find more information about it in the expressjs documentation for middleware

Koa2: how to write chain of middleware?

So in express, we can have a chain of middleware, copies an example:
middleware = function(req, res){
res.send('GET request to homepage');
});
app.get('/', middleware, function (req, res) {
res.send('GET request to homepage');
});
What's the equivalent way to write this in koa2 please ?
I'm thinking of using it for the route, for each route i want to have a middleware to check if user is already logged in.
Thanks !
If you're simply interested in making sure a middlware runs for every route, all you have to do is register the middleware before you register your routing middelware.
app.use(middleware);
As long as you call this before you 'use' your router, it will be called for every request. Just make sure you call the next function. This is how your middleware might look like:
function middleware(ctx, next) {
// Authenticate user
// Eventually call this
return next();
}

How to exit from a stack of middleware in Express.js

I am working a REST web application backend and I got some problem when linking my middleware together.
For example, the stack of the middlewares that each request has to go through is like [before1, service, after1], and here's the code for the middleware "before1", this is just the code I used for testing:
'use strict';
var express = require('express');
var router = express.Router();
router.use(function(request, response, next){
console.log('This is middleware BEFORE1');
var success = true
if (!success){
// Go the logging middleware underneath
next();
}
else{
// Go to the 'service' middleware
next('route');
}
})
router.use(function(request, response, next){
console.log('This is middleware LOGGING');
response.sendStatus(400);
response.end();
})
module.exports = router;
The above code is simply saying if the 'before1' succeeds, it should go straight to call 'service' middleware, and otherwise go to the logging middleware underneath and end the request. But my problem is that I can't figure out a way that it could skip the logging middleware, I searched and found next('route') could help, but it didn't work here. What have I missed?
Thanks in advance!
EDIT:
Or more preferably, it's the best if I can issue an error in any of my middleware and handle all types of errors properly using a error handler middleware.
The skeleton of my top level code is the following:
// An array of middleware to be executed asynchronously
operations = [before1, service, before2];
async.series(operations, function(err) {
if(err) {
// one of the functions passed back an error so handle it here
console.log('Handling error!!!!');
res.end();
// return next(err);
}
console.log('middleware get executed');
// no errors so pass control back to express
next();
});
But I am not sure How should change my middlewares accordingly in order to do that.
next is a node-style callback, which means fn(err, ..), so your next('route') will only work to invoke errorhandlers.
You can implement your series directly by supplying an array of functions to the route, and using an express error handler as the catch all (see http://expressjs.com/guide/error-handling.html)

What does middleware and app.use actually mean in Expressjs?

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

Resources