Welcome to the Linux Foundation Forum!

Lesson 9. Route Validation with Fastify

Hi, everyone.

1.- I'm testing the response schema in the post route, if I intentionally change the return line inside the handler to {test: 'test'} to break the schema validation for 201 response the route still works and return a 201 statusCode without any error. Unlike the get route where if I intentionally change the return line inside the handler to {test: 'test'} the response is 500 with the message "\"brand\" is required!". Here the code of /routes/bicycle/index.js:

'use strict'
const { promisify } = require('util')
const { bicycle } = require('../../model')
const read = promisify(bicycle.read)
const create = promisify(bicycle.create)
const update = promisify(bicycle.update)
const del = promisify(bicycle.del)

const dataSchema = {
    type: 'object',
    required: ['brand', 'color'],
    additionalProperties: false,
    properties:{
        brand: {
            type: 'string'
        },
        color: {
            type: 'string'
        }
    }
}

const idSchema = {
    type: 'integer'
}

const paramSchema = {
    id: idSchema
}
const bodySchema = {
    type: 'object',
    required: ['data'],
    additionalProperties: false,
    properties: {
        data: dataSchema
    }
}

module.exports = async (fastify, opts) => {
    const { httpErrors} = fastify
    fastify.get('/:id', {
                    schema: {
                        params: paramSchema,
                        response: {
                            200: dataSchema
                        }
                    }
        }, async(request, reply) => {
            return { test: 'test'}

        }
    )

    fastify.post('/', {
                    schema: {
                        body: bodySchema, 
                        response: {
                            201: {
                                id: idSchema
                            }
                        }
                    }
        }
        , async (request, reply) => {
            reply.code(201)
            return { test: 'test'}
        }
    )
}

Testing the routes:

For GET:
[[email protected] practices-nodejs-course-lfw212]$ node -e "http.get('http://localhost:3000/bicycle/3', (res)=> res.setEncoding('utf8').once('data', console.log))"

The output: {"statusCode":500,"error":"Internal Server Error","message":"\"brand\" is required!"}

For POST:
[[email protected] practices-nodejs-course-lfw212]$ node -e "http.request('http://localhost:3000/bicycle', { method: 'post', headers: {'content-type': 'application/json'}}, (res) => res.setEncoding('utf8').once('data', console.log.bind(null, res.statusCode))).end(JSON.stringify({data: {brand: 'AnotherBrand', color: 'brown'}}))"

The output: 201 {}

2.- Changing the return line inside the handler in the post route to { id: 'id with wrong type'} that is the correct property but with a wrong type (string instead of integer) the response is the same 201 with an empty json.

3.- If I change the 201 response schema in the post route to:

{
    type: 'object',
    required: ['id'],
    additionalProperties: false,
    properties:{
        id: idSchema
    }
}

The output is the expected for the above cases ( returning { test: 'test'} or { id: 'id with wrong type'}) a 500 code with the message id is required. This makes sense since the previous schema does not tell Fastify that the response is an object and that the property id is required.

But if I change again the return line inside the handler to a simple string 'Wrong type' the output is a successful response code, This happens even in the get route with its dataSchema schema, when I change the return line to return 'Wrong type'

For GET:
[[email protected] practices-nodejs-course-lfw212]$ node -e "http.get('http://localhost:3000/bicycle/1', (res)=> res.setEncoding('utf8').once('data', console.log.bind(null, res.statusCode)))"

The output: 200 Wrong type

For POST:
[[email protected] practices-nodejs-course-lfw212]$ node -e "http.request('http://localhost:3000/bicycle', { method: 'post', headers: {'content-type': 'application/json'}}, (res) => res.setEncoding('utf8').once('data', console.log.bind(null, res.statusCode))).end(JSON.stringify({data: {brand: 'AnotherBrand', color: 'brown'}}))"

The output: 201 Wrong type

Any thoughts? Looks like Fastify does not contemplate this last case when a return is of a different type of the declared in the schema

Thanks in advance.

Gusmen.

Comments

  • @gusmenp I spoke with the lead maintainer of Fastify, this is a known issue. It's because of a rough edge in the implementation, this is one of those 99%/1% situations where in practice it's not ideal but generally quite rare and not a huge issue. However, in the next major release (v4) they are anticipating some of the more fundamental internal changes will enable this to be addressed.

Categories

Upcoming Training