Categories
Fastify

Server-Side Development with Fastify — Request Validation with External Libraries

Spread the love

Fastify is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Fastify.

Ajv Validation Options

We can add validation options with the fastify.setValidatorCompiler method.

For example, we can write:

const fastify = require('fastify')({
  ajv: {
    plugins: [
      require('ajv-merge-patch')
    ]
  }
})

const Ajv = require('ajv')
const ajv = new Ajv({
  removeAdditional: true,
  useDefaults: true,
  coerceTypes: true,
  nullable: true,
})
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
  return ajv.compile(schema)
})

fastify.post('/', {
  handler (req, reply) { reply.send({ ok: 1 }) },
  schema: {
    body: {
      $patch: {
        source: {
          type: 'object',
          properties: {
            q: {
              type: 'string'
            }
          }
        },
        with: [
          {
            op: 'add',
            path: '/properties/q',
            value: { type: 'number' }
          }
        ]
      }
    }
  }
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

We call the Ajv constructor and call the serValidationCompiler method with it to add the options from the object we pass into the Ajv constructor.

We can validate options with other libraries.

For example, we can use the @hapi/joi component.

To use it, we write:

const fastify = require('fastify')({})
const Joi = require('@hapi/joi')

fastify.post('/', {
  schema: {
    body: Joi.object().keys({
      hello: Joi.string().required()
    }).required()
  },
  validatorCompiler: ({ schema, method, url, httpPart }) => {
    return data => schema.validate(data)
  }
}, (request, reply) => {
  reply.send('hello')
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

to add the module.

We call the Joi.object method to make sure the request body is an object.

And we call required to make it required.

Also, we add the validatorCompiler method to add a function to connect the schema to the route.

Also, we can use the yup library to add validator for requests.

For instance, we can write:

const fastify = require('fastify')({})
const yup = require('yup')
const yupOptions = {
  strict: false,
  abortEarly: false,
  stripUnknown: true,
  recursive: true
}

fastify.post('/', {
  schema: {
    body: yup.object({
      age: yup.number().integer().required(),
      sub: yup.object().shape({
        name: yup.string().required()
      }).required()
    })
  },
  validatorCompiler: ({ schema, method, url, httpPart }) => {
    return (data) => {
      try {
        const result = schema.validateSync(data, yupOptions)
        return { value: result }
      } catch (e) {
        return { error: e }
      }
    }
  }
}, (request, reply) => {
  reply.send('hello')
})

const start = async () => {
  try {
    await fastify.listen(3000, '0.0.0.0')
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

to add validation for the request body.

We call yup.number().integer().required() to make a required number field.

And we call yup.object().shape() to validate objects.

And we call yup.string().required() to add a required string field.

Conclusion

We can add validations for requests with external libraries with Fastify apps.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *