Skip to content

Client (web browser) hangs if body not consumed #246

@fishcakeday

Description

@fishcakeday

When trying to abort POST request when using Hono with node-server, it is impossible to abort without consuming the whole body (which is wasteful, especially for large uploads).

Tried with node versions:
v22.17.0
v24.3.0

Hono 4.8.2
Hono 4.8.3

Below is the simplest example:

import { serve } from "@hono/node-server";
import { HTTPException } from "hono/http-exception";
import { Hono } from "hono";

const app = new Hono();

// Works
app.post(
  "/upload1",
  async (ctx) => {
    if (!ctx.req.raw.body) {
      throw new HTTPException(400, { message: "No file data received" });
    }
    // Create "/dev/null" writeable stream, without this the client will hang
    const nullStream = createWriteStream("/dev/null");
    ctx.req.raw.body.pipeTo(Writable.toWeb(nullStream))

    return ctx.json({ ok: "ok" });
  },
);

// Works
app.post(
  "/upload2",
  async (ctx) => {
    return ctx.json({ ok: "ok" });
  },
);

// Hangs
app.post(
  "/upload3",
  async (ctx) => {
    if (!ctx.req.raw.body) {
      throw new HTTPException(400, { message: "No file data received" });
    }

    return ctx.json({ ok: "ok" });
  },
);

// Hangs
app.post(
  "/upload4",
  async (ctx) => {
    if (!ctx.req.raw.body) {
      throw new HTTPException(400, { message: "No file data received" });
    }
    ctx.req.raw.body.cancel();
    return ctx.json({ ok: "ok" });
  },
);

serve(
  {
    fetch: app.fetch,
    port: 3000,
  },
  (info) => {
    console.log(`Server is running on http://localhost:${info.port}`);
  },
);

I suspect it is because of the how it is done in the following part, but I am speculating here.

init.body = Readable.toWeb(incoming) as ReadableStream<Uint8Array>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions