Update request body schema according to the provided route param in runtime
- Dominant language
- No language data
- Stars
- 68
- Forks
- 8
- Avg merge
- 11h 2m
- Merged PRs (30d)
- 2
Description
## 💬 Question here
Is it possible to update a route's request body schema (`request.routeOptions.schema.body`) according to the provided route param in runtime, using the `preValidation` hook? It's possible to achieve this using the `preHandler` hook but that's past the builtin validation stage of the request, and requires manually validating the request body.
This is my schema:
```ts
import { type RouteShorthandOptions } from 'fastify';
import { z } from 'zod';
const userInteractionKindSchema = z.enum(['bookmark', 'reaction', 'feedback']);
const bookmarkPayloadSchema = z.object({
bookmark: z.boolean(),
});
const reactionPayloadSchema = z.object({
reaction: z.enum(['like', 'dislike']).nullable(),
});
const feedbackPayloadSchema = z.object({
feedback: z.string(),
});
const userInteractionPayloadSchemaByKind = {
[userInteractionKindSchema.enum.bookmark]: bookmarkPayloadSchema,
[userInteractionKindSchema.enum.reaction]: reactionPayloadSchema,
[userInteractionKindSchema.enum.feedback]: feedbackPayloadSchema,
};
const updateUserInteractionRouteSchema = {
params: z.object({
interactionKind: userInteractionKindSchema,
}),
body: z.union([
bookmarkPayloadSchema,
reactionPayloadSchema,
feedbackPayloadSchema,
]),
} satisfies RouteShorthandOptions['schema'];
```
And this is my route:
```ts
import { type ZodTypeProvider } from 'fastify-type-provider-zod';
fastify.withTypeProvider().put(
'/userInteractions/:interactionKind',
{
schema: updateUserInteractionRouteSchema,
// doesn't work
preValidation: async request => {
const interactionKindPayloadSchema = userInteractionPayloadSchemaByKind[
request.params.interactionKind
];
request.routeOptions.schema.body = interactionKindPayloadSchema /* requires `as any` to work */;
},
// works, but requires manual validation
preHandler: async request => {
const interactionKindPayloadSchema =
userInteractionPayloadSchemaByKind[request.params.interactionKind];
try {
interactionKindPayloadSchema.parse(request.body);
} catch (error) {
throw new Error(
'Invalid request body for the provided interaction kind',
{ cause: error },
);
}
},
},
(request, reply) => { ... },
);
```
Updating `request.routeOptions.schema.body` in the `preValidation` hook doesn't seem to work - when getting a request for the `"bookmark"` interaction kind with `{ "reaction": "like" }` as the body, which matches another interaction kind's schema, the handler is reached even though it should fail. My current workaround is to manually validate the request body in the `preHandler` hook.
## Your Environment
- *node version*: 20.10.0
- *fastify version*: 4.24.3
- *os*: Mac
Contributor guide
Assessment
This issue has not been assessed yet.