fastify-type-provider-json-schema-to-ts icon indicating copy to clipboard operation
fastify-type-provider-json-schema-to-ts copied to clipboard

Unknown request body when using onRequest hook

Open gurumaxi opened this issue 2 years ago • 7 comments

Prerequisites

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

Issue

When using a hook like onRequest, the schema validation doesn't work anymore. If e.g. a body schema is specified in MySchema, the request body will be of type unknown:

const appWithTypeProvider = app.withTypeProvider<JsonSchemaToTsProvider>();
appWithTypeProvider.post('/', {schema: MySchema, onRequest: randomMethod}, async (request) => {
  request.body // unknown
});

Is this wanted behaviour?

gurumaxi avatar Aug 12 '22 14:08 gurumaxi

Notice: in the onRequest hook, request.body will always be undefined, because the body parsing happens before the preValidation hook.

https://www.fastify.io/docs/latest/Reference/Hooks/#onrequest

Checkout the hooks execution order here: https://www.fastify.io/docs/latest/Reference/Lifecycle/#lifecycle

Eomm avatar Aug 13 '22 07:08 Eomm

In this case, the body is also of type unknown when using a preHandler hook. According to https://www.fastify.io/docs/latest/Reference/Lifecycle/#lifecycle, the preHandler hook is called after the validation, so it should be defined right?

gurumaxi avatar Aug 13 '22 15:08 gurumaxi

the preHandler hook is called after the validation, so it should be defined right?

Yes, the body is set on that time

Eomm avatar Aug 14 '22 08:08 Eomm

In this case, the body is also of type unknown when using a preHandler hook. According to https://www.fastify.io/docs/latest/Reference/Lifecycle/#lifecycle, the preHandler hook is called after the validation, so it should be defined right?

I stumbled on to the same issue with the preHandler hook. So if I define the schema and use an inline hook, the request body is inferred correctly in the actual handler:

server.post(
  "/items",
  {
    schema: {
      body: {
        type: "object",
        properties: {
          name: {
            type: "string",
          },
        },
        required: ["name"],
      } as const,
    },
    // Inline dummy hook
    preHandler: async (request, reply) => {},
  },
  async (request, reply) => {
    // No problems here, request.body.name is a string like it should be
    console.log(request.body.name);
  }
);

However, if I extract the hook into its own function (for reuse purposes and whatnot), then request.body is unknown:

const dummyHook = async (request: FastifyRequest, reply: FastifyReply) => {};

server.post(
  "/items",
  {
    schema: {
      body: {
        type: "object",
        properties: {
          name: {
            type: "string",
          },
        },
        required: ["name"],
      } as const,
    },
    // Hook is now a dedicated function
    preHandler: dummyHook 
  },
  async (request, reply) => {
    // TS2571: Object is of type 'unknown'.
    console.log(request.body.name);
  }
);

Is this expected behaviour? Reusing hooks sounds like a common scenario so I might be missing something. One way to work around this is to call the shared hook from the inline hook but it comes off as being a bit redundant:

  {
    schema: {
        ...
    },
    preHandler: async (request, reply) => {
      await dummyHook(request, reply);
    },
  },
  async (request, reply) => {
    // No problems here, request.body.name is a string like it should be
    console.log(request.body.name);
  }

coocos avatar Sep 13 '22 12:09 coocos

I'm also facing issue described in last comment.

@Eomm maybe it worth to reopen this for visibility that specifying preHandler with dedicated function breaks typing? Or maybe just add a README note about "known issue" and workaround for it.

SkeLLLa avatar Jun 18 '23 14:06 SkeLLLa

Please re-open. I've been hitting this issue as well and haven't found a feel-good work-around. @mcollina.

james-gardner avatar Jan 09 '24 12:01 james-gardner

Ran into this issue as well with type information being lost when using a prehandler that is an external method

johanbook avatar May 23 '24 10:05 johanbook