Request

The instance of the request class allows you to access data for the current HTTP request, including the request body, uploaded files, cookies and much more.

You can access the request object from the HTTP context instance passed to the route handler, middleware, and exception handler.

Route.get('/', (ctx) => {
console.log(ctx.request.url())
})

With destructuring

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

Request data

You can access the request data using one of the following methods.

Route.post('posts', async ({ request }) => {
/**
* Access the entire request body
*/
console.log(request.body())
/**
* Access the parsed query string object
*/
console.log(request.qs())
/**
* A merged copy of the request body and the query
* string
*/
console.log(request.all())
/**
* Cherry pick fields from the "request.all()" output
*/
console.log(request.only(['title', 'description']))
/**
* Omit fields from the "request.all()" output
*/
console.log(request.except(['csrf_token', 'submit']))
/**
* Access value for a single field
*/
console.log(request.input('title'))
console.log(request.input('description'))
})

Query string and params

The parsed query string can be accessed using the request.qs() method.

request.qs()

The request.params() method returns the route parameters.

Route.get('/posts/:id/:slug', async ({ request }) => {
/*
* URL: /posts/1/hello-world
* Params: { id: '1', slug: 'hello-world' }
*/
console.log(request.params())
})

You can also access a single parameter using the request.param method.

request.param('id')
// Default value for optional params
request.param('id', 1)

Request body

The request body is parsed using the pre-configured bodyparser middleware. Open the start/kernel.ts file and ensure that the following middleware is registered inside the list of the global middlewares.

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

Once the bodyparser middleware has been registered, you can use one of the following methods to access the request body.

request.body()
// A merged copy of query string and the request body
request.all()

The request.input method allows reading value for a single field. Optionally, you can define a default value to be returned when the actual value is null or undefined.

request.input('title')
// If title is missing
request.input('title', 'Hello world')

The request.only and request.except method allows selecting or ignoring specific fields.

// Cherry pick
const body = request.only(['title', 'description'])
// Omit
const body = request.except(['submit', 'csrf_token'])

Supported content types

The bodyparser is capable of parsing the following content types.

JSON

The JSON parser processes request sending the JSON string with one of the following content types.

You can add more content types to the json.types array inside the config/bodyparser.ts file, and the JSON parser will also process them.


URL encoded

Request sending a URL encoded string with content-type='application/x-www-form-urlencoded' is parsed using the URL encoding parser.


Multipart

The multipart requests with content-type='multipart/form-data' are parsed using the multipart parser. Make sure to read the guide on file uploads to view all available configuration options.


Raw

All requests with content-type='text/*' are read using the raw parser. You can further process the raw string inside a middleware or the route handler.

You can use the raw parser to process custom/unsupported content types. For example

Register the custom content type

config/bodyparser.ts
{
raw: {
// ...
types: ['text/*', 'my-custom-content-type']
}
}

Create a middleware to parse the content type further

Route
.get('/', ({ request }) => {
console.log(request.all())
})
.middleware(async ({ request }, next) => {
const contentType = request.header('content-type')
if (contentType === 'my-custom-content-type') {
const body = request.raw()
const parsed = someCustomParser(body)
request.updateBody(parsed)
}
await next()
})

Request route

The request class holds the current matching route for the HTTP request and you can access it as follows:

Route.get('/', ({ request }) => {
/**
* The route pattern
*/
console.log(request.route.pattern)
/**
* The handler that handles the route request
*/
console.log(request.route.handler)
/**
* Middleware attached to the route
*/
console.log(request.route.middleware)
/**
* Route name (exists if route is named)
*/
console.log(request.route.name)
})

You can also check if the current request URL matches a given route or not.

if (request.matchesRoute('/posts/:id')) {
}

Or pass an array to check for more than one route. The method returns true if any of the routes match the current request URL.

if (request.matchesRoute(['/posts/:id', '/posts/:id/comments'])) {
}

Request URL

You can access the request URL using the request.url() method. It returns the pathname without the domain name or the port.

request.url()
// Include query string
request.url(true)

The request.completeUrl() method returns the complete URL, including the domain and the port (if any).

request.completeUrl()
// Include query string
request.completeUrl(true)

Request method

method

Returns the HTTP method for the given request. The spoofed method is returned when form method spoofing is enabled.

request.method()

intended

The intended method returns the actual HTTP method and not the spoofed one.

request.intended()

Request id

Request ids help you debug and trace logs for a given HTTP request by associating a unique id to every log entry.

AdonisJS follows the industry standard and has first-class support for working with the X-Request-Id header.

Generating request ids

Open the config/app.ts and set the value of http.generateRequestId to true.

Also, the request-id is only generated when the X-Request-Id header is not set. This allows you to generate the request ids at your proxy server level and then reference them inside your AdonisJS application.

config/app.ts
{
http: {
generateRequestId: true
}
}

Access request id

The request.id() method returns the request-id by reading the X-Request-Id header. The flow looks as follows:

request.id()

Request id inside logs

The logger instance attached to the HTTP context automatically sets the request_id property on every log statement.

Route.get('/', ({ logger }) => {
// { msg: 'hello world', request_id: 'ckk9oliws0000qt3x9vr5dkx7' }
logger.info('hello world')
})

Request headers

The request.headers() and the request.header() method gives you access to the request headers.

// all headers
console.log(request.headers())

The header method returns the value for a single header field. The header name is not case sensitive.

request.header('X-CUSTOM-KEY') === request.header('x-custom-key')
// With default value
request.header('x-header-name', 'default value')

Request IP address

The request.ip() method returns the most trusted IP address for the HTTP request. Make sure to read the trusted proxy section to understand how you can get the correct IP address when your application is behind a proxy server.

request.ip()

The request.ips() method returns an array of IP addresses starting from the most trusted to the least trusted IP address.

request.ips()

Custom IP reterval method

If the trusted proxy settings are not enough to determine the correct IP address, you can implement your own custom getIp method.

Open the config/app.ts file and define the getIp method as follows:

http: {
getIp(request) {
const nginxRealIp = request.header('X-Real-Ip')
if (nginxRealIp) {
return nginxRealIp
}
return request.ips()[0]
}
}

Form method spoofing

Standard HTML forms cannot make use of all the HTTP verbs beyond GET and POST. It means you cannot create a form with the method PUT.

However, AdonisJS allows you to spoof the HTTP method using the _method query string. In the following example, the request will be routed to the route listening for the PUT request.

<form method="POST" action="/posts/1?_method=PUT"></form>

Form method spoofing only works:

Content negotiation

Content negotiation is a mechanism that is used for serving different representations of a resource from the same URL.

The client making the request can negotiate for the resource representation, charset, language, and encoding using different Accept headers, and you can handle them as follows.

request.accepts

The request.accepts method takes an array of content types (including shorthands) and returns the most appropriate content type by inspecting the Accept header. You can find the list of supported content types here .

Route.get('posts', async ({ request, view }) => {
const posts = [
{
title: 'Adonis 101',
},
]
switch (request.accepts(['html', 'json'])) {
case 'html':
return view.render('posts/index', { posts })
case 'json':
return posts
default:
return view.render('posts/index', { posts })
}
})

request.language

Negotiate for the requested language based upon the Accept-language header.

const language = request.language(['fr', 'de'])
if (language) {
return view.render(`posts/${language}/index`)
}
return view.render('posts/en/index')

request.encoding

Find the best encoding using the Accept-encoding header.

switch (request.encoding(['gzip', 'br'])) {
case 'gzip':
return compressAsGzip(someValue)
case 'br':
return compressAsBr(someValue)
default:
return value
}

request.charset

Find the best charset using the Accept-charset header.

const charset = request.charset(['utf-8', 'hex', 'ascii'])
return Buffer.from('hello-world').toString(charset || 'utf-8')

Trusted proxy

The majority of Node.js applications are deployed behind a proxy server like Nginx or Caddy. Hence, the value of remoteAddress is the IP address of the proxy server and not the client.

However, all the proxy servers set the X-Forwaded headers to reflect the request's original values, and you must inform AdonisJS to trust the proxy server headers.

You can control which proxies to trust by modifying the http.trustProxy value inside the config/app.ts.

config/app.ts
{
http: {
trustProxy: proxyAddr.compile(valueComesHere)
}
}

Boolean values

Setting the value to true will trust the left-most entry in the X-Forwarded-* header. Whereas the false assumes the application directly faces the Internet and value for request.connection.remoteAddress is used.

{
trustProxy: proxyAddr.compile(true)
}

Ip addresses

You can also define a single or an array of proxy server IP addresses to trust.

{
trustProxy: proxyAddr.compile('127.0.0.0/8')
}
// or
{
trustProxy: proxyAddr.compile(['127.0.0.0/8', 'fc00:ac:1ab5:fff::1/64'])
}

The following shorthand keywords can also be used in place of IP addresses.

Custom function

You can also define a custom function that returns a boolean on a per request basis.

{
trustProxy: proxyAddr.compile((address, index) => {
return address === '127.0.0.1' || address === '123.123.123.123'
})
}

Proxy headers in use

The following methods from the request class rely on a trusted proxy to return the correct value.

CORS

AdonisJS has in-built support for responding to the CORS OPTIONS requests. Just enable it inside the config/cors.ts file.

config/cors.ts
{
enabled: true,
// ...rest of the config
}

The config file is extensively documented. Make sure to go through all the options and read the associated comments to understand its usage.

Other methods and properties

Following is the list of other available methods and properties on the Request class.

updateBody

Allows you to update the request body with a custom payload. It would be best if you weren't doing it unless creating a package that purposefully mutates the request body.

request.updateBody(myCustomPayload)

updateRawBody

The updateRawBody allows updating the raw request body. The raw body is always a string.

request.updateRawBody(JSON.stringify(myCustomPayload))

updateQs

The updateQs allows updating the value of parsed query string.

request.updateQs(someCustomParser(request.parsedUrl.query))

original

Returns the request's original body parsed by the bodyparser. Calling the updateBody method does not change the original payload.

request.original()

hasBody

Find if the request has a body. The bodyparser uses this method to know if the request has a body before parsing it.

if (request.hasBody()) {
// parse request body
}

Extending Request class

You can extend the Request class using macros or getters. The best place to extend the request is inside a custom service provider.

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

import { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
public static needsApplication = true
constructor(protected app: ApplicationContract) {}
public async boot() {
const Request = this.app.container.use('Adonis/Core/Request')
Request.macro('wantsJSON', function () {
const types = this.types()
return (
types[0] && (types[0].includes('/json') || types[0].includes('+json'))
)
})
}
}

In the above example, we have added the wantsJSON method to the request class. It reads the Accept header's value and returns true if the first value negotiates for JSON.

You can use the newly added method as follows.

Route.get('/', ({ request }) => {
if (request.wantsJSON()) {
return {}
}
})

Informing typescript about the method

The wantsJSON property is added at the runtime, and hence TypeScript does not know about it. To inform the TypeScript, we will use declaration merging and add the property to the RequestContract interface.

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

contracts/request.ts
declare module '@ioc:Adonis/Core/Request' {
interface RequestContract {
wantsJSON(): boolean
}
}

Additional reading

Following are some of the additional guides to learn more about the topics not covered in this document.