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())
})
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
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.
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('aMethod', function (this: HttpContext) {
return value
}
HttpContext.getter('aProperty', 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()