CORS error issues when passing `Content-Type: application/json` from the client
What version of Hono are you using?
3.11.11
What runtime/platform is your app running on?
Vercel
What steps can reproduce the bug?
// app/api/[[...route]]/route.ts
import { Hono } from "hono";
import { cors } from "hono/cors";
import { handle } from "hono/vercel";
export const runtime = "edge";
const app = new Hono().basePath("/api");
app.use("*", cors());
app.post("/test", async (c) => {
const body = await c.req.json();
return c.json({ ok: true, body });
});
export const POST = handle(app);
// Client
const res = await fetch("http://localhost:3001/api/test", {
method: "POST",
headers: { "Content-Type": "application/json", },
body: JSON.stringify({ hello: "world" }),
});
// ❌ Error: CORS error
// Client
const res = await fetch("http://localhost:3001/api/test", {
method: "POST",
body: JSON.stringify({ hello: "world" }),
});
// ✅ It works
However, when using zValidator from @hono/zod-validator, I experience this:
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { handle } from "hono/vercel";
import { z } from "zod";
export const runtime = "edge";
const app = new Hono().basePath("/api");
app.use("*", cors());
const schema = z.object({
hello: z.string(),
});
app.post("/test", zValidator("json", schema), async (c) => {
const body = await c.req.valid("json");
return c.json({ ok: true, body });
});
export const POST = handle(app);
// Client
const res = await fetch("http://localhost:3001/api/test", {
method: "POST",
body: JSON.stringify({ hello: "world" }),
});
// ❌ Error: 400 Bad Request
// { success: false, message: "Invalid HTTP header: Content-Type=text/plain;charset=UTF-8" }
// Client
const res = await fetch("http://localhost:3001/api/test", {
method: "POST",
headers: { "Content-Type": "application/json", },
body: JSON.stringify({ hello: "world" }),
});
// ❌ Error: CORS error
What is the expected behavior?
I should get CORS to work when passing Content-Type: application/json from the client.
What do you see instead?
No response
Additional information
Dependencies:
"@hono/zod-validator": "^0.1.11",
"hono": "^3.11.11",
"next": "14.0.4",
"react": "^18",
"react-dom": "^18",
"zod": "^3.22.4",
Hi @jferrettiboke
I can't reproduce it. Please share the minimal project to reproduce it.
I confirm I can reproduce this. It only happens when:
- Running Hono in local using Vercel.
- Performing a request from the browser that contains any headers.
I've been doing some digging and I believe it's related to this issue from Vercel: https://github.com/vercel/vercel/issues/10927
I just started a new Hono project with Bun and I'm encountering this issue as well. Version 3.12.6. My first time using Hono and can not for the life of me figure out what I'm doing wrong with my barebones setup that is pretty much like the OP's example.
I went back and installed older version of hono to trace down when it did last work. I worked my way up from [email protected] but I never encountered the cors issue again. Even all the way back up to the latest version at 3.12.6? Perhaps there's a missing dependency in the latest package but the error is being swallowed?
EDIT:
Actually, it seems to be related to const app = new Hono().basePath('/api'). I had to remove this for 3.0 because I was getting errors that basePath was not a function of Hono. Adding it back in on version 3.12.6 started triggering the cors errors again. If I remove the basePath and route using app.post("/api/test", ...) Everything works as expected.
Hi @frankieali
This works fine on Bun.
import { zValidator } from '@hono/zod-validator'
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { raw } from 'hono/html'
import { z } from 'zod'
const schema = z.object({
hello: z.string(),
})
const app = new Hono().basePath('/api')
app.use('/api/*', cors())
app.post('/test', zValidator('json', schema), (c) => {
const body = c.req.valid('json')
return c.json({ ok: true, body })
})
app.get('/', (c) => {
return c.html(
<html>
<body>
<script>
{raw(`
(async () => {
const res = await fetch("http://localhost:3000/api/test", {
method: "POST",
headers: { "Content-Type": "application/json", },
body: JSON.stringify({ hello: "world" }),
})
console.log(await res.json())
})();`)}
</script>
</body>
</html>
)
})
export default app
I can't reproduce it on Bun. And it's not related to Vercel's matter. We can close it now