fastify-sensible icon indicating copy to clipboard operation
fastify-sensible copied to clipboard

Strict schema validation of methods fails

Open ollebergkvist opened this issue 1 year ago • 4 comments

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have searched existing issues to ensure the bug has not already been reported

Fastify version

4.28.1

Plugin version

5.6.0

Node.js version

20.17.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.7.6

Description

I noticed that when I add .strict() schema validation in my response schemas (zod), reply.*() breaks.

Eg. reply.unauthorized() returns this response:

{
	"statusCode": 401,
	"error": "Unauthorized",
	"message": "Unauthorized"
}

This fails:

export const routeSchema = {
  response: {
    401: z
      .object({
        statusCode: z.literal(401),
        error: z.literal('Unauthorized'),
        message: z.string()
      }).strict()
    }
}

With this error:

{
	"statusCode": 500,
	"code": "FST_ERR_FAILED_ERROR_SERIALIZATION",
	"message": "Failed to serialize an error. Error: Response doesn't match the schema. Original error: Unauthorized"
}

This works:

export const routeSchema = {
  response: {
    401: z
      .object({
        statusCode: z.literal(401),
        error: z.literal('Unauthorized'),
        message: z.string()
      })
    }
}

Link to code that reproduces the bug

No response

Expected Behavior

Should be possible to add strict validation.

ollebergkvist avatar Oct 11 '24 17:10 ollebergkvist

Thanks for reporting!

Can you provide steps to reproduce? We often need a reproducible example, e.g. some code that allows someone else to recreate your problem by just copying and pasting it. If it involves more than a couple of different file, create a new repository on GitHub and add a link to that.

mcollina avatar Oct 12 '24 11:10 mcollina

@mcollina

Sure, I can set time aside to create a small reproducible example at some point this week 👍

ollebergkvist avatar Oct 14 '24 17:10 ollebergkvist

@mcollina

I created a reproducible example here 👍: https://github.com/ollebergkvist/fastify-sensible-strict-schema-example

ollebergkvist avatar Oct 21 '24 03:10 ollebergkvist

When you use reply.unauthorized() an instance of HttpError is created:

https://github.com/fastify/fastify-sensible/blob/0244a15adc935b3f7866752bd575e4eb1328cd6d/lib/httpError.d.ts#L1-L10

This object is the data that is passed into the schema validation. As you can see in the above type definition, you would need to at least also test for status and expose:

z
  .object({
    status: z.literal(400),
    statusCode: z.literal(400),
    expose: z.boolean(),
    error: z.literal("Bad Request"),
    message: z.string(),
  })
  .strict()

Zegnat avatar Jan 12 '25 21:01 Zegnat