HTTP context

HTTP context

A new instance of HTTP Context class is generated for every HTTP request and passed along to the route handler, middleware, and exception handler.

HTTP Context holds all the information you may need related to an HTTP request. For example:

  • You can access the request body, headers, and query params using the ctx.request property.
  • You can respond to the HTTP request using the ctx.response property.
  • Access the logged-in user using the ctx.auth property.
  • Authorize user actions using the ctx.bouncer property.
  • And so on.

In a nutshell, the context is a request-specific store holding all the information for the ongoing request.

Getting access to the HTTP context

The HTTP context is passed by reference to the route handler, middleware, and exception handler, and you can access it as follows.

Route handler

The router handler receives the HTTP context as the first parameter.

import router from '@adonisjs/core/services/router'
router.get('/', (ctx) => {
console.log(ctx.inspect())
})
Destructure properties
import router from '@adonisjs/core/services/router'
router.get('/', ({ request, response }) => {
console.log(request.url())
console.log(request.headers())
console.log(request.qs())
console.log(request.body())
response.send('hello world')
response.send({ hello: 'world' })
})

Controller method

The controller method (similar to the router handler) receives the HTTP context as the first parameter.

import { HttpContext } from '@adonisjs/core/http'
export default class HomeController {
async index({ request, response }: HttpContext) {
}
}

Middleware class

The handle method of the middleware class receives HTTP context as the first parameter.

import { HttpContext } from '@adonisjs/core/http'
export default class AuthMiddleware {
async handle({ request, response }: HttpContext) {
}
}

Exception handler class

The handle and the report methods of the global exception handler class receive HTTP context as the second parameter. The first parameter is the error property.

import {
HttpContext,
HttpExceptionHandler
} from '@adonisjs/core/http'
export default class ExceptionHandler extends HttpExceptionHandler {
async handle(error: unknown, ctx: HttpContext) {
return super.handle(error, ctx)
}
async report(error: unknown, ctx: HttpContext) {
return super.report(error, ctx)
}
}

Injecting Http Context using Dependency Injection

If you use Dependency injection throughout your application, you can inject the HTTP context to a class or a method by type hinting the HttpContext class.

Ensure the #middleware/container_bindings_middleware middleware is registered inside the kernel/start.ts file. This middleware is required to resolve request-specific values (i.e., the HttpContext class) from the container.

See also: IoC container guide

app/services/user_service.ts
import { inject } from '@adonisjs/core'
import { HttpContext } from '@adonisjs/core/http'
@inject()
export default class UserService {
constructor(protected ctx: HttpContext) {}
all() {
// method implementation
}
}

For automatic dependency resolution to work, you must inject the UserService inside your controller. Remember, the first argument to a controller method will always be the context, and the rest will be injected using the IoC container.

import { inject } from '@adonisjs/core'
import { HttpContext } from '@adonisjs/core/http'
import UserService from '#services/user_service'
export default class UsersController {
@inject()
index(ctx: HttpContext, userService: UserService) {
return userService.all()
}
}

That's all! The UserService will now automatically receive an instance of the ongoing HTTP request. You can repeat the same process for nested dependencies as well.

Accessing HTTP context from anywhere inside your application

Dependency injection is one way to accept the HTTP context as a class constructor or a method dependency and then rely on the container to resolve it for you.

However, it is not a hard requirement to restructure your application and use Dependency injection everywhere. You can also access the HTTP context from anywhere inside your application using the Async local storage provided by Node.js.

We have a dedicated guide on how Async local storage works and how AdonisJS uses it to provide global access to the HTTP context.

In the following example, the UserService class uses the HttpContext.getOrFail method to get the HTTP context instance for the ongoing request.

app/services/user_service.ts
import { HttpContext } from '@adonisjs/core/http'
export default class UserService {
all() {
const ctx = HttpContext.getOrFail()
console.log(ctx.request.url())
}
}

The following code block shows the UserService class usage inside the UsersController.

import { HttpContext } from '@adonisjs/core/http'
import UserService from '#services/user_service'
export default class UsersController {
index(ctx: HttpContext) {
const userService = new UserService()
return userService.all()
}
}

HTTP Context properties

Following is the list of properties you can access through the HTTP context. As you install new packages, they may add additional properties to the context.

ctx.request

Reference to an instance of the HTTP Request class.

ctx.response

Reference to an instance of the HTTP Response class.

ctx.logger

Reference to an instance of logger created for a given HTTP request.

ctx.route

The matched route for the current HTTP request. The route property is an object of type StoreRouteNode

ctx.params

An object of route params

ctx.subdomains

An object of route subdomains. Only exists when the route is part of a dynamic subdomain

ctx.session

Reference to an instance of Session created for the current HTTP request.

ctx.auth

Reference to an instance of the Authenticator class. Learn more about authentication.

ctx.view

Reference to an instance of Edge renderer. Learn more about Edge in View and templates guide

ctx.ally

Reference to an instance of the Ally Manager class to implement social login in your apps. Learn more about Ally

ctx.bouncer

Reference to an instance of the Bouncer class. Learn more about Authorization.

ctx.i18n

Reference to an instance of the I18n class. Learn more about i18n in Internationalization guide.

Extending HTTP context

You may add custom properties to the HTTP context class using macros or getters. Make sure to read the extending AdonisJS guide first if you are new to the concept of macros.

import { HttpContext } from '@adonisjs/core/http'
HttpContext.macro('property', function (this: HttpContext) {
return value
}
HttpContext.getter('property', function (this: HttpContext) {
return value
})

Since the macros and getters are added at runtime, you must inform TypeScript about their types using module augmentation.

import { HttpContext } from '@adonisjs/core/http'
declare module '@adonisjs/core/http' {
export interface HttpContext {
aMethod: () => ValueType
aProperty: ValueType
}
}
HttpContext.macro('aMethod', function (this: HttpContext) {
return value
}
HttpContext.getter('aProperty', function (this: HttpContext) {
return value
})

Creating dummy context during tests

You may use the testUtils service to create a dummy HTTP context during tests.

The context instance is not attached to any route; therefore, the ctx.route and ctx.params values will be undefined. However, you can manually assign these properties if required by the code under test.

import testUtils from '@adonisjs/core/services/test_utils'
const ctx = testUtils.createHttpContext()

By default, the createHttpContext method uses fake values for the req and the res objects. However, you can define custom values for these properties as shown in the following example.

import { createServer } from 'node:http'
import testUtils from '@adonisjs/core/services/test_utils'
createServer((req, res) => {
const ctx = testUtils.createHttpContext({
req,
res
})
})

Using the HttpContext factory

The testUtils service is only available inside an AdonisJS application; therefore, if you are building a package and need access to a fake HTTP context, you may use the HttpContextFactory class.

import { HttpContextFactory } from '@adonisjs/core/factories/http'
const ctx = new HttpContextFactory().create()