Request

This guide gives an outline on how to make use of the HTTP Request object to read data for a request.

The Node.js raw req object can be accessed as request.request.

AdonisJs passes the current HTTP request object as part of the context which is sent to all route handlers and middleware.

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

We used ES6 destructuring to get the request object from context.

Request body

The request object offers a bunch of helpful methods to read the request body. First, make sure that you have installed the body-parser middleware.

If not, follow the upcoming steps.

Setting up bodyparser

Fullstack and API only boilerplates comes with pre-configured body-parser.
adonis install @adonisjs/bodyparser

Then register the provider inside start/app.js file

const providers = [
  '@adonisjs/bodyparser/providers/BodyParserProvider'
]

Also, register the global middleware inside start/kernel.js file.

const globalMiddleware = [
  'Adonis/Middleware/BodyParser'
]

Methods

Following is the list of methods you can call to read the request body.

all

Returns the request body as an object. This method merges the query params with the request body.

const all = request.all()

get

Get an object of query params

const query = request.get()

post

Get an object of just request body

const body = request.post()

raw

Get data posted as the raw body.

If raw data is JSON with Content-type: application/json, then the bodyparser parses it smartly and returns it as part of post method.
const body = request.raw()

only

Returns an object with only specified keys

const body = request.only(['username', 'email', 'age'])

except

The opposite of only and returns everything except defined keys.

const body = request.except(['csrf_token', 'submit'])

input

Get value for a given key only, and it does not exist, return the default value.

const drink = request.input('drink')

// with default value
const drink = request.input('drink', 'coffee')

Request collection

Quite often you want to handle HTML forms that submit an array of data over key/value pairs. For example: Form to create multiple users at once.

<form method="POST" action="/users">
  <input type="text" name="username[0]" />
  <input type="text" name="age[0]" />

  <hr>
  <input type="text" name="username[1]" />
  <input type="text" name="age[1]" />
</form>

Let’s say we want to get the username and age inside the controller.

const users = request.only(['username', 'age'])

// output
{ username: ['virk', 'nikk'], age: [26, 25] }

The above piece of data is something that you cannot save to the database directly since it is not in the right format.

Using request.collect we can get it formatted out of the box.

const users = request.collect(['username', 'age'])

// output
[{ username: 'virk', age: 26 }, { username: 'nikk', age: 25 }]

// save to db
await User.createMany(users)

Headers

Also, you can read headers from the request using one of the following methods.

header

The header value for a given key.

const auth = request.header('authorization')

// different word case
const auth = request.header('Authorization')

headers

Returns an object of headers.

const headers = request.headers()

Cookies

Cookies are read using one of the following methods

Returns the value for a key inside cookies. Optionally returns the default value.

const cartTotal = request.cookie('cart_total')

// with default value
const cartTotal = request.cookie('cart_total', 0)

cookies

Returns an object of all the cookies

const cookies = request.cookies()

Since all cookies are encrypted and signed automatically, you cannot read values for cookies set via Javascript on browser. Instead consider using one of the following methods.

plainCookie

const jsCookie = request.plainCookie('cart_total')

plainCookies

Get an object of raw cookies

const plainCookies = request.plainCookies()

Content negotiation

Content negotiation is a way for server and client to decide upon the best response type to be returned from the server.

Content negotiation can also be done on the basis on route formats. Learn more about it here

Since web servers do not only serve web pages, they have to deal with API response in JSON, or maybe in XML. Instead of creating separate URL’s for each content type, the consumer can ask the server to return the response in a specific format.

Now to construct the response in a specific format, the server needs to know it first. The same can be done using the accepts method.

accepts

Reads the Accept header to know response format.

const bestFormat = request.accepts(['json', 'html'])

if (bestFormat === 'json') {
  return response.json(users)
}

return view.render('users.list', { users })

language

Language can also be negotiated based upon Accept-Language header.

const language = request.language(['en', 'fr'])

Request methods

Following is the list of all request methods and their usage example

url

Returns the current request url

const url = request.url()

originalUrl

The URL with query strings on it

const url = request.originalUrl()

method

Returns the request HTTP method.

const method = request.method()

intended

Since Adonisjs allows method spoofing, you can fetch the actual method using intended method.

const method = request.intended()

ip

Returns the most trusted ip address for the user.

const ip = request.ip()

ips

Returns an array of ips from most to the least trusted one. It removes the default ip address, which can be accessed via ip method.

const ips = request.ips()

subdomains

Returns a list of request subdomains, this method removes www from the list.

const subdomains = request.subdomains()

ajax

Checks for X-Requested-With header to determine if the request is ajax or not.

if (request.ajax()) {
  // do something
}

pjax

Pjax is an evolved way to make use of Ajax to deliver better user experience on traditional apps. In rails world, it is known as Turbolinks.

This methods looks at X-PJAX header to identify if request is pjax or not.

if (request.pjax()) {
  // do something
}

hostname

Returns the request hostname

const hostname = request.hostname()

protocol

Return request protocol.

const protocol = request.protocol()

match

Matches a set of expressions against the current request URL to tell if it matches one.

// current request url - posts/1

request.match(['posts/:id']) // returns true

hasBody

A boolean indicating if the request has post body. It is mainly used by the bodyparser to know whether to parse the body or not.

if (request.hasBody()) {
  // do something
}

is

The is method returns the best matching content type for the current request. The check is entirely based upon the content-type header.

// assuming content-type is `application/json`

request.is(['json', 'html']) // returns - json

request.is(['application/*']) // returns - application/json

Method spoofing

HTML forms are only capable of making GET and POST requests, which means you cannot utilize the REST conventions of using other HTTP methods like PUT, DELETE and so on.

AdonisJs makes it simpler bypassing the request method as part of the query string and then it executes the correct Route for you automatically.

Route.put('users', 'UserController.update')
<form method="POST" action="/users?_method=PUT">

The above works in following cases.

  1. The original request method has to be POST.

  2. allowMethodSpoofing is enabled inside config/app.js file.

Extending Request

Quite often you have the requirement of extending the Request prototype by attaching new methods. Same can be done by defining a macro on the Request class.

Application Specific

If your macros are specific to your application only, you can add the macro inside start/hooks.js file after the providers have been booted.

start/hooks.js
const { hooks } = require('@adonisjs/ignitor')

hooks.after.providersBooted(() => {
  const Request = use('Adonis/Src/Request')

  Request.macro('cartValue', function () {
    return this.cookie('cartValue', 0)
  })
})

Via Provider

If you are writing a module/addon for AdonisJs, you can add a macro inside the boot method of your service provider.

const { ServiceProvider } = require('@adonisjs/fold')

class MyServiceProvider extends ServiceProvider {
  boot () {
    const Request = use('Adonis/Src/Request')

    Request.macro('cartValue', function () {
      return this.cookie('cartValue', 0)
    })
  }
}

Defined macros can be used like any other request method.

const cartValue = request.cartValue()