Skip to main content
The RequestValidator class provides a convenient API for validating HTTP request data using VineJS validators. It automatically includes request body, files, URL parameters, headers, and cookies in the validation data.

Importing

import { RequestValidator } from '@adonisjs/core/http'

Overview

The RequestValidator is accessible through the request object in your HTTP context:
import { HttpContext } from '@adonisjs/core/http'

export default class UsersController {
  async store({ request }: HttpContext) {
    const data = await request.validateUsing(createUserValidator)
  }
}

Static Properties

errorReporter

Custom error reporter function for all validations.
import { RequestValidator } from '@adonisjs/core/http'
import { SimpleErrorReporter } from '@vinejs/vine'

RequestValidator.errorReporter = (ctx) => {
  return new SimpleErrorReporter()
}
errorReporter
(ctx: HttpContext) => ErrorReporterContract
Function that returns an error reporter instance based on the HTTP context

messagesProvider

Custom messages provider for all validations.
import { RequestValidator } from '@adonisjs/core/http'
import { messages } from '#validators/messages'

RequestValidator.messagesProvider = (ctx) => {
  return messages
}
messagesProvider
(ctx: HttpContext) => MessagesProviderContact
Function that returns a messages provider instance based on the HTTP context

Methods

validateUsing()

Validate HTTP request data using a VineJS validator. Throws a ValidationError if validation fails.
import vine from '@vinejs/vine'

const createUserValidator = vine.compile(
  vine.object({
    email: vine.string().email(),
    name: vine.string().minLength(3),
    password: vine.string().minLength(8)
  })
)

export default class UsersController {
  async store({ request }: HttpContext) {
    const data = await request.validateUsing(createUserValidator)
    // data is fully typed based on the validator schema
  }
}
validator
VineValidator<Schema, MetaData>
VineJS validator instance created with vine.compile()
options
RequestValidationOptions<MetaData>
Optional validation options:
  • errorReporter: Custom error reporter function
  • messagesProvider: Custom messages provider
  • data: Custom data to validate (overrides default request data)
  • Additional VineJS validation options
Returns: Promise<Infer<Schema>> Throws: ValidationError if validation fails

tryValidateUsing()

Validate HTTP request data without throwing errors. Returns a tuple with either the error or validated data.
export default class UsersController {
  async store({ request, response }: HttpContext) {
    const [error, data] = await request.tryValidateUsing(createUserValidator)
    
    if (error) {
      return response.unprocessableEntity({
        errors: error.messages
      })
    }
    
    // Use validated data
    const user = await User.create(data)
    return response.created({ user })
  }
}
validator
VineValidator<Schema, MetaData>
VineJS validator instance created with vine.compile()
options
RequestValidationOptions<MetaData>
Optional validation options (same as validateUsing)
Returns: Promise<[ValidationError, null] | [null, Infer<Schema>]>

Validation Data

By default, the validator includes the following data from the request:
  • Body data: All form fields and JSON data
  • Files: Uploaded files
  • URL parameters: Route parameters (available as params)
  • Headers: Request headers (available as headers)
  • Cookies: Request cookies (available as cookies)
const validator = vine.compile(
  vine.object({
    // Request body
    email: vine.string().email(),
    name: vine.string(),
    
    // Route parameters
    params: vine.object({
      id: vine.number()
    }),
    
    // Headers
    headers: vine.object({
      authorization: vine.string()
    }),
    
    // Cookies
    cookies: vine.object({
      session_id: vine.string()
    })
  })
)

Validation Options

Custom Error Reporter

Provide a custom error reporter for specific validations:
import { SimpleErrorReporter } from '@vinejs/vine'

const data = await request.validateUsing(createUserValidator, {
  errorReporter: () => new SimpleErrorReporter()
})

Custom Messages

Provide custom validation messages:
const messages = {
  'email.required': 'Email address is required',
  'email.email': 'Please provide a valid email address',
  'password.minLength': 'Password must be at least {{ min }} characters'
}

const data = await request.validateUsing(createUserValidator, {
  messagesProvider: messages
})

Custom Validation Data

Validate custom data instead of request data:
const customData = {
  email: 'user@example.com',
  name: 'John Doe'
}

const data = await request.validateUsing(createUserValidator, {
  data: customData
})

Metadata

Pass metadata to validators that require it:
const updateUserValidator = vine.withMetaData<{ userId: number }>().compile(
  vine.object({
    email: vine.string().email()
  })
)

const data = await request.validateUsing(updateUserValidator, {
  meta: { userId: 1 }
})

Creating Validators

Create reusable validators in a separate file:
// validators/user.ts
import vine from '@vinejs/vine'

export const createUserValidator = vine.compile(
  vine.object({
    email: vine.string().email().normalizeEmail(),
    name: vine.string().minLength(3).maxLength(50),
    password: vine.string().minLength(8).confirmed(),
    age: vine.number().min(18).optional()
  })
)

export const updateUserValidator = vine.compile(
  vine.object({
    email: vine.string().email().normalizeEmail().optional(),
    name: vine.string().minLength(3).maxLength(50).optional(),
    age: vine.number().min(18).optional()
  })
)
Use in controllers:
import { createUserValidator, updateUserValidator } from '#validators/user'

export default class UsersController {
  async store({ request }: HttpContext) {
    const data = await request.validateUsing(createUserValidator)
    return User.create(data)
  }
  
  async update({ request, params }: HttpContext) {
    const data = await request.validateUsing(updateUserValidator)
    const user = await User.findOrFail(params.id)
    await user.merge(data).save()
    return user
  }
}

Error Handling

Validation errors are automatically formatted and include:
try {
  await request.validateUsing(createUserValidator)
} catch (error) {
  // error.messages contains formatted error messages
  console.log(error.messages)
  /*
  [
    {
      field: 'email',
      message: 'The email field must be a valid email address',
      rule: 'email'
    },
    {
      field: 'password',
      message: 'The password field must be at least 8 characters',
      rule: 'minLength',
      args: { min: 8 }
    }
  ]
  */
}

Global Configuration

Configure validators globally in a provider:
// providers/app_provider.ts
import { ApplicationService } from '@adonisjs/core/types'
import { RequestValidator } from '@adonisjs/core/http'
import { SimpleErrorReporter } from '@vinejs/vine'
import { messages } from '#validators/messages'

export default class AppProvider {
  constructor(protected app: ApplicationService) {}
  
  async boot() {
    // Global error reporter
    RequestValidator.errorReporter = () => {
      return new SimpleErrorReporter()
    }
    
    // Global messages provider
    RequestValidator.messagesProvider = () => {
      return messages
    }
  }
}

Example: Complex Validation

import vine from '@vinejs/vine'
import { HttpContext } from '@adonisjs/core/http'

// Validator with nested objects and arrays
const createOrderValidator = vine.compile(
  vine.object({
    customer: vine.object({
      name: vine.string().minLength(3),
      email: vine.string().email(),
      phone: vine.string().mobile()
    }),
    items: vine.array(
      vine.object({
        productId: vine.number(),
        quantity: vine.number().min(1),
        price: vine.number().min(0)
      })
    ).minLength(1),
    shippingAddress: vine.object({
      street: vine.string(),
      city: vine.string(),
      state: vine.string(),
      zipCode: vine.string().postal()
    }),
    paymentMethod: vine.enum(['card', 'paypal', 'cash'])
  })
)

export default class OrdersController {
  async store({ request, response }: HttpContext) {
    const [error, data] = await request.tryValidateUsing(createOrderValidator)
    
    if (error) {
      return response.unprocessableEntity({
        message: 'Validation failed',
        errors: error.messages
      })
    }
    
    const order = await Order.create(data)
    return response.created({ order })
  }
}

Type Safety

The validator provides full TypeScript type inference:
const validator = vine.compile(
  vine.object({
    email: vine.string().email(),
    age: vine.number(),
    isActive: vine.boolean().optional()
  })
)

const data = await request.validateUsing(validator)
// data type is inferred as:
// {
//   email: string
//   age: number
//   isActive?: boolean
// }