GitShow/honojs/node-server
honojs

node-server

Node.js Server for Hono

by honojs
honohttp-servernodejsserver
Star on GitHubForkWebsitenpm

TypeScript

676 stars107 forks58 contributorsActive · 5h agoSince 2022v2.1.3MIT

Meet the team

See all 58 on GitHub →
yusukebe
yusukebe222 contributions
usualoma
usualoma51 contributions
BlankParticle
BlankParticle10 contributions
tangye1234
tangye12344 contributions
tavvy
tavvy3 contributions
Jayllyz
Jayllyz2 contributions
GavinMeierSonos
GavinMeierSonos2 contributions
mgcrea
mgcrea2 contributions

Languages

View on GitHub →
TypeScript92.3%
JavaScript7.7%
HTML0%

Commit activity

Last 12 weeks · 22 commits

Full graph →

Community health

2 of 6 standards met

Community profile →
37
✓README✓License○Contributing○Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Active · Last activity 5h ago
See all on GitHub →
haleygu64
[Bug] overrideGlobalObjects: true breaks openapi-fetch middleware instanceof checksOpenIssue

What version of Hono are you using? : 4.11.7 : 1.19.9 What runtime/OS are you seeing the problem on? Bun 1.2.19 (Linux) Also reproduced on Node.js v22.17.1 What steps can reproduce the bug? When 's runs with (the default), it replaces and with lightweight polyfills. Libraries that validate objects via or break silently because the objects returned by native were constructed with the original classes, not Hono's replacements. Minimal reproduction with : Upstream mock (any server returning JSON on ). Trigger: Bun test proving the issue What is the expected behavior? should not break checks in third-party libraries. Returning the same / object from middleware callbacks should work regardless of . What do you see instead? internally validates middleware returns with: The object returned by native was constructed with the original class, but after , checks against Hono's replacement polyfill — which fails. Root cause 's replaces and with lightweight alternatives. Any library relying on or to validate objects created by the native will break, because native fetch constructs objects using the original constructors, not the replacements. Additional context This affects any library that uses or for validation, not just . The pattern is common in HTTP middleware ecosystems (, , custom fetch wrappers, etc.).

haleygu64 · 1w ago
colinhacks
perf(response): defer streams when copying response headersOpenPR

Preserve buffered string/null bodies when Hono copies a finalized response to update its headers. The optional constructor hook copies headers without constructing a ReadableStream, and the cached writer records consumption so saved response aliases cannot replay the body. Body observation materializes native responses sharing the same stream. Unsupported responses use the existing path, including streams, mutable byte arrays, subclasses, proxies and already-observed bodies. Shared groups are capped at 64 wrappers. The companion Hono change, https://github.com/honojs/hono/pull/5350, calls the hook before reading the body. Without it, the adapter retains the existing behavior. No application changes or runtime-specific condition are required. Performance Runnable reproduction, custom fixtures and raw results: hono-response-copy-benchmark. The repository builds the exact source revisions below and includes a second clean-VM verification run. These are custom fixtures, not Hono's official benchmark suite. With both PRs applied, mixed-route throughput improved 65%, eight-header throughput 62%, and 64 KiB response throughput 31%.** Application code was identical across controls. These gains require both the Hono hook and the adapter implementation; neither PR alone enables the fast path. Median requests/second: Node 26.8.1 on a dedicated Linux GCE n2-standard-8 VM. HTTP/1.1 loopback, 32 connections, two wrk threads, server and client pinned to separate physical cores. Three interleaved repetitions, each with a two-second warmup and five-second measurement. Mixed traffic was 80% middleware-backed parameter routes across 16 routes and 4,096 IDs, 10% text and 10% JSON. At two connections, mixed throughput improved from 14,973 to 25,679 requests/second (+71%). The comparison used source-built Hono and adapter as controls, versus Hono and adapter . Subsequent commits add tests only. These are short, closed-loop fixture measurements, not production latency or application-wide performance claims. Tests Added header-copy, alias-consumption, fallback and real HTTP GET/HEAD regressions. Full suite: 448 passed on Node 20 and 22; 449 passed on Node 22 after adding the Content-Type regression. Typecheck, lint, format and ESM/CJS build passed. Cross-package differential checks passed on Node 20, 22, 24 and 26; CJS integration passed. Full suites on Node 24/26 retained one/three request partial-read or disconnect failures, respectively, reproduced on the unchanged base with the same dependencies.

colinhacks · 3w ago

Recent fixes

View closed PRs →
usualoma
fix(listener): avoid mutating response headers when setting Content-LengthMergedPR

This PR fixes #400 while also optimizing Content-Length handling on the HTTP/1 response fast paths. I confirmed that copying the header record, as suggested in #400, also resolves the issue. In local benchmarks with Hono 4.13.8, that approach showed a performance regression on Node 20, but no clear regression on Node 22 or 24. It remains a reasonable option to consider. #401 already implements that approach. However, the original reporter offered, “Happy to open a PR if the approach looks right.” If we decide to proceed with the copying approach, I think we should respect that offer, close #401 for now, and give the reporter the opportunity to submit their PR. Implementation This PR uses Node’s internal field to let Node serialize the length without copying caller-owned header records. The same mechanism also handles responses without custom headers, avoiding explicit Content-Length header processing. This deliberately depends on Node.js implementation details, including private response fields whose behavior is not guaranteed by the public API. node-server has made similar implementation-dependent optimizations several times before. Given the measured improvements in the response fast paths, I consider the gains substantial enough to justify this dependency. Compatibility guards retain explicit-length fallbacks for HTTP/2 and other cases where automatic serialization cannot preserve the existing behavior. The regression tests check both response correctness and whether the intended fast paths are used. These tests run in the existing Node.js CI matrix, so incompatible changes should be detected promptly when an affected Node.js release is tested. Benchmarks The final implementation was compared with the baseline (, v2.1.0) and a plain-header-copy variant on an Apple M5 Pro (arm64, macOS). Each variant ran in five independent processes, with rotating execution order. Each process performed 300,000 warm-up requests followed by five samples of 200,000 requests, using natural GC. The table reports median time per request in nanoseconds; lower is better. This includes Hono dispatch, response creation, and Node’s header serialization. Socket I/O is excluded. In these runs, copying increased processing time by 33.89% on Node 20, while showing no slowdown on Node 22 or 24. The copy column measures the benchmark harness’s plain-record-copy implementation, rather than the exact #401 implementation. A control case using JSON with seven additional headers exercises the conversion path. Its median changes were −1.42%, −0.72%, and −0.47% on Node 20, 22, and 24 respectively, with overlapping baseline and candidate ranges. These small differences do not establish an improvement on that path.

usualoma · 7h ago
agustin18
fix(listener): avoid mutating caller header object when setting Content-LengthMergedPR

Fixes #400 Description In , when is a plain object and no was specified, mutated the caller's header object in place. If that header object is reused across responses (e.g., a module-level constant) or frozen via : 1. On reused plain headers, subsequent requests trigger a (HTTP 500) because Hono's response handler iterates non-string values as multi-value headers. 2. On frozen headers, direct mutation throws (HTTP 500). Solution Instead of mutating the incoming object in place, create a shallow copy with only when it needs to be injected: Tests Added parameterized tests covering , , and bodies to ensure caller header objects remain unmodified across sequential requests. Added test verifying frozen header objects () do not cause runtime errors. Verified all 439 tests pass cleanly.

agustin18 · 7h ago
lacherogwu
Header object passed to c.body() is mutated, so reusing it returns 500 from the second request onClosedIssue

What version of are you using? 2.1.1 (with 4.13.8, Node v24.19.0, macOS) What is the problem? When a handler passes a plain object as the third argument of , the adapter writes into that object. If the object is reused across responses — a module-level constant, for example — the next response fails with and the server returns 500. So the first request succeeds and every subsequent one fails, which is an unpleasant failure mode to debug: it looks like a caching or concurrency problem rather than a mutated constant. Minimal reproduction Output: Cause In , when is a plain object the is assigned directly to it: https://github.com/honojs/node-server/blob/main/src/listener.ts#L228-L235 The and array branches just above build a new object via , so only the plain-object path mutates its input. Since Hono keeps the caller's object as the response's header init, that write lands on the object the handler owns. The 500 on the following request then comes from Hono's side: walks the header record and treats any non-string value as an iterable of values, and is now a number: Why it is easy to miss never goes through this adapter, so a test suite that exercises handlers in-process passes cleanly while production fails from the second request onward. In our case the bug reached a deployed service with full coverage of the affected route. Suggested fix Copy before writing, so the caller's object is left as it was: Using a string value would also be more consistent with the rest of the header record, though the copy is the part that fixes the reuse case. Happy to open a PR if the approach looks right.

lacherogwu · 7h ago
Structured data for AI agents

Repository: honojs/node-server. Description: Node.js Server for Hono Stars: 676, Forks: 107. Primary language: TypeScript. Languages: TypeScript (92.3%), JavaScript (7.7%), HTML (0%). License: MIT. Homepage: https://hono.dev Topics: hono, http-server, nodejs, server. Latest release: v2.1.3 (4h ago). Open PRs: 14, open issues: 31. Last activity: 5h ago. Community health: 37%. Top contributors: yusukebe, usualoma, BlankParticle, tangye1234, tavvy, Jayllyz, GavinMeierSonos, mgcrea, nakasyou, otnc and others.

·@ofershap

Replace github.com with gitshow.dev