Last updated 6 months ago

Data sent from client side cannot be trusted. This document shows you different tools to perform server side input validation.

Ajv, the JSON Schema Validator

FoalTS validation is based on Ajv, a fast JSON Schema Validator. You'll find more details on how to define a shema on its website.

FoalTS's baseline ajv configuration is:

coerceTypes: true, // change data type of data to match type keyword
removeAdditional: true, // remove additional properties
useDefaults: true, // replace missing properties and items with the values from corresponding default keyword

The validate util

The validate util throws a ValidationError if the given data does not fit the shema.


import { validate } from '@foal/core';
const schema = {
properties: {
a: { type: 'number' }
type: 'object'
const data = {
a: 'foo'
validate(schema, data);
// => Throws an error (ValidationError)
// => error.content contains the details of the validation error.

The ValidateBody, ValidateHeaders, ValidateParams and ValidateQuery hooks

ValidateBody, ValidateHeaders, ValidateParams and ValidateQuery are hooks to control the body, headers, route params and the query of the requests received by the server. They validate context.request.{body|headers|params|query} with the given schema. If the validation fails then an HttpResponseBadRequest is returned with the validation errors as body.


import { Context, HttpResponseOK, Post, ValidateBody } from '@foal/core';
export class MyController {
additionalProperties: false,
properties: {
firstName: { type: 'string' },
lastName: { type: 'string' },
required: [ 'firstName', 'lastName' ],
type: 'object'
postUser(ctx: Context) {
// In this function we are sure that firstName and lastName
// are defined thanks to the above hook.
console.log(ctx.request.body.firstName, ctx.request.body.lastName);
return new HttpResponseOK();

In this example, if you try to POST /user with a JSON object that does not have a firstName property, you'll get returned a 400 BAD REQUEST with this body:

"keyword": "required",
"dataPath": "",
"schemaPath": "#/required",
"params": {
"missingProperty": "firstName"
"message": "should have required property 'firstName'"