diff --git a/docs/src/app/(docs)/backend-adapters/fetch/page.mdx b/docs/src/app/(docs)/backend-adapters/fetch/page.mdx index 8e5d8625ac..050dd0d7e9 100644 --- a/docs/src/app/(docs)/backend-adapters/fetch/page.mdx +++ b/docs/src/app/(docs)/backend-adapters/fetch/page.mdx @@ -120,6 +120,35 @@ new Elysia() }); ``` + + **Heads up if you refactor the handler shape.** The example above works + because Elysia's static analyzer leaves `ev.request` alone. If you + rewrite either route to the more idiomatic destructured form — + `({ request }) => handlers(request)` — the analyzer infers the route + reads `body` and Elysia pre-parses the request via `request.json()`, + consuming the stream before UploadThing's handler can read it. The + client sees a silent empty-body 400. + + The fix is to opt out of body parsing for the route by passing + `{ parse: "none" }` as the third argument: + + ```ts + .get("/api/uploadthing", ({ request }) => handlers(request), { + parse: "none", + }) + .post("/api/uploadthing", ({ request }) => handlers(request), { + parse: "none", + }) + ``` + + This is the same option Elysia uses internally for its own + [`.mount()` method](https://elysiajs.com/patterns/mount.html) and is + documented under + [explicit parsers](https://elysiajs.com/essential/life-cycle.html#explicit-parser). + See [elysiajs/elysia#1252](https://github.com/elysiajs/elysia/issues/1252) + for background. + + ### Hono ```ts diff --git a/examples/backend-adapters/server/src/elysia.ts b/examples/backend-adapters/server/src/elysia.ts index 9df54bb1df..f87161e01f 100644 --- a/examples/backend-adapters/server/src/elysia.ts +++ b/examples/backend-adapters/server/src/elysia.ts @@ -9,6 +9,14 @@ const handler = createRouteHandler({ router: uploadRouter, }); +// The `(ev) => handler(ev.request)` shape is intentional — it keeps +// Elysia's static analyzer from inferring the route reads `body` and +// pre-parsing the request, which would consume the stream before +// UploadThing's handler reads it. If you rewrite to the idiomatic +// `({ request }) => handler(request)`, add `{ parse: "none" }` as the +// route's third arg to opt out of body parsing. See the Elysia callout +// in docs/src/app/(docs)/backend-adapters/fetch/page.mdx and +// elysiajs/elysia#1252. new Elysia() .get("/api", () => "Hello from Elysia!") .get("/api/uploadthing", (ev) => handler(ev.request))