We’ve experienced writing middleware that performs its function and hands off the request and response objects to the next function in the stack, but why exactly do we have to write
next() at the end of every middleware? If it always needs to be at the end of every function we write, it seems like an unnecessary piece of boilerplate. You might be surprised to learn that we aren’t going to introduce a way to automatically hand off the request and response objects without having to repeatedly write
next(). Rather, we’re going to explore why it is useful to have
next() as a separate function call. The biggest reason being we don’t always want to pass control to the next middleware in the stack.
For example, when designing a system with confidential information, we want to be able to selectively show that information to authorized users. In order to do that, we would create middleware that tests a user’s permissions. If the user has the permission necessary, we would continue through the middleware stack by calling
next(). If it fails, we would want to let the user know that they’re not allowed to see the information they’re trying to access.
Notice how our middleware correctly calls
next. If your
if block is entered (meaning the bean does not exist), the function
returns to break from the middleware. We could also achieve the same result by putting all the code after the
if block in an
next is called at the end of the middleware callback function. This placement ensures that if a bean does not exist, the proper error status is sent, but if it does exist, we attach it to the request object and proceed to the next matching route/middleware to complete the request-response cycle.