Built-in validator formData parsing
What version of Hono are you using?
4.46
What runtime/platform is your app running on?
Nodejs
What steps can reproduce the bug?
Is there a reason at this you use arrayBuffer to construct formData record? https://github.com/honojs/hono/blob/d21f8eb27aa43da9cd9d5b6f666692c4e92a0344/src/validator/validator.ts#L92
Hono has a built-in for that already c.req.parseBody()
This causes a bug if there's middleware which uses .parseBody() before validator - this populates c.req.bodyCache.parsedBody AND c.req.bodyCache.formData.
And since your validator tries to check the cache for formData(not parsedBody) - it gets a hit which contains FormData, not a Record.
It seems this issue would be mitigated if either hono used c.req.bodyCache.parsedBody with a fallback to arrayBuffer or would just use parseBody() directly since it already checks the cache.
So is there some reason for the current behavior? Apologies that the issue isn't properly filled in but I hope my explanation is clear enough.
What is the expected behavior?
No response
What do you see instead?
No response
Additional information
No response
Hi @HugeLetters
This causes a bug if there's middleware which uses
.parseBody()before validator - this populatesc.req.bodyCache.parsedBodyANDc.req.bodyCache.formData.
Can you provide the concrete steps to reproduce that bug first?
@yusukebe hi, here's small demo https://github.com/HugeLetters/formdata-hono-demo
Just run a dev script and it should provide logs which showcase the bug.
@HugeLetters Thanks! I'll check it later.
@HugeLetters Sorry for the late reply.
I'm investigating it now. I've created a minimal code to reproduce it:
import assert from 'assert'
import { Hono } from 'hono'
import { validator } from 'hono/validator'
const app = new Hono().post(
'/',
async (c, next) => {
await c.req.parseBody()
await next()
},
validator('form', (value) => {
console.log('validator - value:', value)
assert(!(value instanceof FormData), 'Value has to be a Record, not FormData')
return value
}),
(c) => {
return c.text('Hello Hono!')
}
)
const form = new FormData()
form.append('foo', 'bar')
await app.request('/', {
method: 'POST',
body: form
})