Introduction

Middleware provides a simple way to analyse and filter HTTP requests as they enter your application. OstroJS, for example, offers a middleware that ensures your application's user is authorised. The middleware will send the user to your application's login screen if the user is not authorised. If the user is authorised, however, the middleware will allow the request to continue inside the application.

Aside from authentication, other middleware may be developed to execute a number of activities. A logging middleware, for example, may log all incoming requests to your application. The OstroJS framework comes with a variety of middleware, including authentication and CSRF protection middleware. The app/http/middleware directory contains all of these middleware.

Defining Middleware

Use the make:middleware Assistant command to create a new middleware:

node assitant make:middleware EnsureTokenIsValid

Within your app/http/middleware directory, this command will create a new EnsureTokenIsValid class. We will only allow access to the route in this middleware if the given token input matches a defined value. Otherwise, visitors will be redirected to the home URI:

class EnsureTokenIsValid {

    handle({ request, redirect, next }) {
        if (request.input('token') !== 'my-secret-token') {
            return redirect.route('home');
        }
        next();
    }
}

As you can see, the middleware will provide an HTTP redirect to the client if the given token does not match our secret token; else, the request will be forwarded further into the application. You should use the next callback with the request to transfer the request farther into the application (allowing the middleware to "pass").

Imagine middleware as a set of "layers" through which HTTP requests must transit before reaching your application. Each layer has the ability to evaluate the request and possibly reject it outright.

 

Registering Middleware

List the middleware class in the $middleware field of your app/http/kernel.js class if you want it to run on every HTTP request to your application.

Assigning Middleware To Routes

If you want to attach middleware to certain routes, you must first assign the middleware a key in the app/http/kernel.js file of your application. This class's routeMiddleware field includes entries for the middleware supplied with OstroJS by default. You may add your own middleware to this list and give it a unique key:

$namedMiddlewares = {
    'guest': require('~/app/http/middleware/redirectIfAuthenticated'),
    'auth': require('~/app/http/middleware/authenticate'),
};

You may use the middleware method to assign middleware to a route once the middleware has been defined in the HTTP kernel:

route.get('/profile', function () {
    //
}).middleware('auth');

By supplying an array of middleware names to the middleware method, you may apply several middleware to the route:

route.get('/', function () {
    //
}).middleware(['first', 'second']);

You may also supply the fully qualified class name when assigning middleware:

route.get('/profile', function () {
    //
}).middleware(EnsureTokenIsValid);

 

Middleware Groups

 

To make assigning middleware to routes easier, you may wish to combine many middleware under a single key. The $middlewareGroups property of your HTTP kernel may be used to do this.

OstroJS comes with web and api middleware groups out of the box, which contain typical middleware you would wish to use on your web and API routes. Remember that your app's app/providers/routeServiceProvider service provider applies these middleware groups to routes within your relevant web and api route files automatically:

/**
 * The application's route middleware groups.
 *
 * @var Object
 */
$middlewareGroups = {
    'web': [
        require('@ostro/http/middleware/bodyParserJson'),
        require('@ostro/http/middleware/bodyParserUrlEncoded'),
        require('@ostro/http/middleware/formParser'),
        require('@ostro/http/middleware/queryParser'),
        require('@ostro/cookie/middleware/cookieParser'),
        require('@ostro/session/middleware/startSession'),
        require('~/app/http/middleware/verifyCsrfToken'),
        require('@ostro/auth/middleware/startAuth'),
    ]
};

The same syntax as individual middleware may be used to apply middleware groups to routes and controller actions. Middleware groups make it easier to apply many middleware to a route at the same time:

Route.get('/', function () {
    //
}).middleware('web');

Route.middleware(['web']).group(function () {
    //
});

Sorting Middleware

It's possible that you'll require your middleware to execute in a certain sequence but won't be able to manage it after it's assigned to the route. In this scenario, the $middlewarePriority property of your app/http/kernel.js file may be used to indicate your middleware priority. This attribute may not be present by default in your HTTP kernel. If it doesn't exist, you can use the following default definition:

/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
$middlewarePriority = [
    '~/app/cookie/middleware/encryptCookies',
    '~/app/session/middleware/startSession',
];

 

Middleware Parameters

Additional arguments can be sent to middleware. For example, if your application wants to check that the authenticated user has a certain "role" before executing a specific operation, you might use the RedirectIfNotAuthenticated middleware, which takes a role name as an extra parameter.

Following the next argument, further middleware parameters will be given to the middleware:

class RedirectIfNotAuthenticated {

    /**
     * Handle an incoming request.
     *
     * @return void
     */
    async handle({redirect,auth,next}) {
        if (! await auth.check()) {
            return redirect.route('login');
        }
        next();
    }
}

module.exports =  RedirectIfNotAuthenticated

Terminable Middleware

At times, a middleware may need to execute certain tasks after the HTTP response has been dispatched to the client. If you define a terminate method in your middleware, it will be automatically invoked when the response is sent to the client, provided that your Node.js server is in use.

class RedirectIfNotAuthenticated {

    /**
     * Handle an incoming request.
     *
     * @return void
     */
    async handle({redirect,auth,next}) {
        if (! await auth.check()) {
            return redirect.route('login');
        }
        next();
    }
    async terminate({next}){
    	next()
}

module.exports =  RedirectIfNotAuthenticated