Middleware

Middleware are a series of functions that are executed during an HTTP request before it reaches the route handler. Every function in the chain has the ability to end the request or forward it to the next function.

Basic Example

The simplest way to test a middleware is to attach it to the route using the Route.middleware method. For example:

Route
.get('/users/:id', async () => {
return 'Show user'
})
.middleware(async (ctx, next) => {
console.log(`Inside middleware ${ctx.request.url()}`)
await next()
})

Middleware classes

Writing middleware as inline functions is fine for some quick testing. However, we recommend extracting the middleware logic to its own file.

You can create a new middleware by running the following ace command.

node ace make:middleware LogRequest
# CREATE: app/Middleware/LogRequest.ts

About middleware class

Middleware classes are stored (but not limited to) inside the app/Middleware directory and each file represents a single middleware.

Every middleware class must implement the handle method to handle the HTTP request and call the next method to forward the request to the next middleware or the route handler.

app/Middleware/LogRequest.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class LogRequest {
public async handle(
{ request }: HttpContextContract,
next: () => Promise<void>
) {
console.log(`-> ${request.method()}: ${request.url()}`)
await next()
}
}

Also, you can terminate requests from the middleware by raising an exception or sending the response using the response.send method.

Make sure you do NOT call the next method when decided to end the request.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class Auth {
public async handle(
{ request, response }: HttpContextContract,
next: () => Promise<void>
) {
if (notAuthenticated) {
response.unauthorized({ error: 'Must be logged in' })
return
}
await next()
}
}

Registering middleware

For the middleware to take effect, it must be registered as a global middleware or a named middleware inside the start/kernel.ts file.

Global middleware

Global middleware are executed for all the HTTP requests in the same sequence as they are registered.

You register them as an array inside the start/kernel.ts file, as shown below:

start/kernel.ts
Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParserMiddleware'),
() => import('App/Middleware/LogRequest')
])

Named middleware

Named middleware allows you to selectively apply middleware on your routes/group of routes. You begin by registering them with a unique name and later reference it on the route by that name.

start/kernel.ts
Server.middleware.registerNamed({
auth: () => import('App/Middleware/Auth')
})

Now, you can attach the auth middleware to a route as shown in the following example.

Route
.get('dashboard', 'DashboardController.index')
.middleware('auth') // 👈

You can also define multiple middleware on a route by passing them as an array or calling the middleware method multiple times.

Route
.get('dashboard', 'DashboardController.index')
.middleware(['auth', 'acl', 'throttle'])
Route
.get('dashboard', 'DashboardController.index')
.middleware('auth')
.middleware('acl')
.middleware('throttle')

Passing config to named middleware

Named middleware can also accept runtime config through the handle method as the third argument. For example:

export default class Auth {
public async handle(
{ request, response }: HttpContextContract,
next: () => Promise<void>
guards?: string[]
) {
await next()
}
}

In the above example, the Auth middleware accepts an optional guards array. The user of the middleware can pass the guards as follows:

Route
.get('dashboard', 'DashboardController.index')
.middleware('auth', ['web', 'api'])

FAQs

How to disable middleware on a given HTTP request?

You cannot disable middleware for a given HTTP request. However, the middleware can accept the runtime config to ignore certain requests.

A great example of this is the bodyparser middleware. It ignores all the requests not matching the whitelisted methods inside the config/bodyparser.ts file.

Are middleware executed on requests with no routes?

AdonisJS does not execute the middleware chain, if there is no registered route for the current HTTP request.