-
-
Notifications
You must be signed in to change notification settings - Fork 621
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Response serialization and validation #2439
Comments
Hi @sher Thank you for sharing your opinion.
Hono does not have a future now. But there have been some discussions before. We tried to implement response validation in Zod OpenAPI, but declined because we thought we needed to work on Hono's core. I think it would be better to make the Response Validator as thin as the current |
Thanks @yusukebe Agree, that the hono API should be as thin as possible and delegate validation to whatever library user wants to use. Currently handlers can accept multiple request validation functions. As the sequence of serialization and validation is reversed in response compared to request, it seems better to handle this inside every handler function before returning data. const schema = z.object({
email: z.string().email(),
password: z.string(),
});
app.post('/me', async function (c) {
const user = D1.findOne({email: c.body.email});
const parsed = schema.safeParse(user);
if (!parsed.success) {
return c.text('Invalid!', 401);
}
return parsed.data;
}); But still this approach is not ideal, we want to specify the shape that has to be returned on every case and let the schema validator to handle the situation. This makes the task bit difficult, because we have to have a common response shape declaration/specification "language", for example json-schema shape. Then the validator should take the shape and validate data against it. |
How about adding const route = app.on(
'LIST_OF_USERS',
'/users',
validator('response:200', (value, c) => {
const parsed = schema.safeParse(value);
if (!parsed.success) {
return c.text('Invalid!', 401);
}
return parsed.data;
}),
validator('response:400', () => {
return {
q: 'bar',
};
}),
(c) => {
return c.json({
success: true,
});
}
); |
My idea is to create another validator like const validationErrorResponse = (reason: string) => {
return new Response(reason, {
status: 401, // We have to set proper status code
})
}
type ResponseValidatorFnResponse<T = any> =
| {
success: true
data: T
}
| {
success: false
reason: string
}
type ResponseValidatorFn<T = any> = (
value: any
) => ResponseValidatorFnResponse<T> | Promise<ResponseValidatorFnResponse<T>>
const responseValidator =
(status: number, validationFn: ResponseValidatorFn) => async (c, next) => {
await next()
if (!c.res.headers.get('content-type')?.startsWith('application/json')) {
c.res = validationErrorResponse('The content is not JSON')
return
}
if (c.res.status !== status) {
c.res = validationErrorResponse(`The status is not ${status}`)
return
}
const value = await c.res.json() // Maybe we have to clone the response body.
const result = await validationFn(value)
if (result.success === false) {
c.res = validationErrorResponse(result.reason)
return
}
const newResponse = new Response(JSON.stringify(result.data))
c.res = newResponse
}
const schema = z.object({
success: z.boolean(),
})
app.get(
'/results',
responseValidator(200, (value) => {
const parsed = schema.safeParse(value)
if (!parsed.success) {
return {
success: false,
reason: parsed.error.message,
}
}
return {
success: true,
data: parsed.data,
}
}),
(c) => {
return c.json({
// Is not typed currently
success: true,
})
}
) |
I have the exact same case, I don't want some fields accidentialy leaking to the client. |
Hey there, I'm dealing with an issue in my project where I'm using Zod for schema validation and Prisma for database interactions within a Hono TypeScript API. I would like TypeScript to throw an error if there's a mismatch between the returned/fetched types (especially when Im playing with relations). For some types it works however, for response types it doesnt seem to work and also it doesnt infer correct type for the response types in openapi schema. How I am tackling the validation of the 200 response type is simply by using However anything request related stuff are working for example calling Here's an example of my code:
What I've Tried:
Additional Information: Environment: |
What is the feature you are proposing?
Certain frameworks (eg: fastify) provide response validation for success or error payloads.
Is there support for such feature in hono? If not, is it something planned?
Context
Apart from obvious advantages like schema-first approach, this feature would greatly help securing API internals.
For example, when you have multiple unique IDs for DB records and you want to make sure that only
external_id
IDs are ever returned without accidentally leakinginternal_id
IDs.The text was updated successfully, but these errors were encountered: