AdonisJS v6 is here. Learn more in our release blog post.


HTTP context is a request-specific object that holds the information like the request body, cookies, headers, the currently logged in user, and much more for a given HTTP request.

The HTTP context is passed by reference to the route handler, middleware, HTTP hooks, and exception handler.

Route.get('/', ({ request, auth, response }) => {
* Request URL
* Request body + query params
* Send response
response.send('hello world')
response.send({ hello: 'world' })
* Available when auth is configured

Make sure to define the HTTP context type explicitly when accessing the context inside a controller method.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
class HomeController {
public async index({ request, response }: HttpContextContract) {

Are there any relation to req and res objects from the Express?

You will not see any req or res objects in AdonisJS. This is because everything, including the request and the response, is part of the HTTP context.

Also, you are encouraged to add your custom properties to the ctx object and NOT to the request object. See Extending context .

Access HTTP context from anywhere

AdonisJS uses the Node.js Async Local Storage to make the HTTP context available anywhere inside your application.

You can access the context for the current request as follows:

import HttpContext from '@ioc:Adonis/Core/HttpContext'
class SomeService {
public async someOperation() {
const ctx = HttpContext.get()


Following is the list of properties available on the HTTP context. As you will install new packages, they may also add more properties to this object.

Output of ctx.inspect({ depth: 0 })
Output of ctx.inspect({ depth: 0 })


Reference to the HTTP request

Route.get('/', async ({ request }) => {})


Reference to the HTTP response

Route.get('/', async ({ response }) => {})


Reference to the logger instance. A child logger instance with a unique request ID is created for every HTTP request.

Route.get('/', async ({ logger }) => {})


Reference to the matched route for the current HTTP request. The route object has the following properties.

  • pattern: The route pattern
  • handler: The route handler
  • middleware: An array of route middleware
  • name: Route name (if any)
Route.get('/', async ({ route }) => {})


An object of route params.

Route.get('users/:id', async ({ params }) => {


An object of route subdomains. Only available when the route is registered with a domain. => {
Route.get('/', async ({ subdomains }) => {


Reference to the Session object . Available only when @adonisjs/session package is installed.

Route.get('/', async ({ session }) => {


Reference to the Auth object . Available only when @adonisjs/auth package is installed.

Route.get('/', async ({ auth }) => {


Reference to the View object . Available only when @adonisjs/view package is installed.

Route.get('/', async ({ view }) => {
return view.render('welcome')


Reference to the Ally object . Available only when @adonisjs/ally package is installed.

Route.get('/', async ({ ally }) => {
return ally.use('github').redirect()


Reference to the Bouncer object . Available only when @adonisjs/bouncer package is installed.

Route.get('/', async ({ bouncer }) => {
await bouncer.authorize('viewPost', post)


Reference to the I18n object . Available only when @adonisjs/i18n package is installed.

Route.get('/', async ({ i18n }) => {
await i18n.formatCurrency(100, { currency: 'EUR' })

Extending Context

The HTTP context object is designed to be extended by other packages or your own application code. A common use case is to attach custom properties inside a middleware. For example:

import geoip from 'geoip-lite'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class UserLocationMiddleware {
public async handle(ctx: HttpContextContract, next: () => Promise<void>) {
ctx.location = geoip.lookup(ctx.request.ip())
await next()

Here we have added a custom location property to the ctx, which you can access inside the route handler or in the upcoming middleware.

Informing TypeScript about the custom property

The location property is added at the runtime; hence TypeScript does not know about it. To inform the TypeScript about its existence, we will use declaration merging and add the property to the HttpContextContract interface.

Create a new file at path contracts/context.ts (the file name is not important) and paste the following contents inside it:

declare module '@ioc:Adonis/Core/HttpContext' {
import { Lookup } from 'geoip-lite'
interface HttpContextContract {
location: Lookup | null

That's all! Now, TypeScript will not complain about the missing property on the ctx object.

Using getters and macros

You can also use getters and macros to add custom properties to the ctx object. In the previous example, we added an instance property to the ctx object. However, getters and macros add the property on the prototype of the class.

Also, there is no need to create a middleware this time since you need to define the macros/getters only once, and they are available for all the instances of the HttpContext class.

Open the pre-existing providers/AppProvider.ts file and paste the following code inside the boot method:

import geoip from 'geoip-lite'
import { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
public static needsApplication = true
constructor(protected app: ApplicationContract) {}
public async boot() {
const HttpContext ='Adonis/Core/HttpContext')
HttpContext.getter('location', function location() {
return geoip.lookup(this.request.ip())

By default, the getters are evaluated on every access. However, you can also mark them as singleton, as shown in the following example:

function location() {
return geoip.lookup(this.request.ip())
true // 👈 register as singleton


Getters are only accessible as properties. However, macros can be both properties and methods.

HttpContext.macro('getLocation', function location() {
return geoip.lookup(this.request.ip())
// Access it as

Or attach a literal value.

// Access it as