hono icon indicating copy to clipboard operation
hono copied to clipboard

CORS error issues when passing `Content-Type: application/json` from the client

Open jferrettiboke opened this issue 2 years ago • 5 comments

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",

jferrettiboke avatar Dec 29 '23 17:12 jferrettiboke

Hi @jferrettiboke

I can't reproduce it. Please share the minimal project to reproduce it.

yusukebe avatar Dec 31 '23 03:12 yusukebe

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

alexiglesias93 avatar Jan 17 '24 13:01 alexiglesias93

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.

frankieali avatar Jan 24 '24 17:01 frankieali

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.

frankieali avatar Jan 24 '24 18:01 frankieali

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

yusukebe avatar Jan 25 '24 20:01 yusukebe

I can't reproduce it on Bun. And it's not related to Vercel's matter. We can close it now

yusukebe avatar Mar 25 '24 17:03 yusukebe