NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #1282 most downloaded on npm
Web framework built on Web Standards
Last release today
04 Oct 2026
Ships on a steady schedule
a new release about every 2 weeks
Nearly every release is documented
notes for 59 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
455 releases · first in 2021
One column per quarter.
Nothing published for this version
fix(build): keep internal types private in bundled d.ts and avoid a self-referencing JSX.IntrinsicElements in #5485
Full Changelog: v4.13.11...v4.13.12
serveStatic decodes the request path a second time, leading to bypass of middleware on static paths
serveStatic decodes the request path a second time, leading to bypass of middleware on static pathsAffects: hono/serve-static and the adapters built on it (hono/bun, hono/deno, hono/cloudflare-workers, @hono/bun, @hono/deno, @hono/cloudflare-workers). Fixes serveStatic decoding an already-decoded path, where a crafted request could be routed as one path and served as another, skipping middleware mounted on a static prefix. GHSA-5r4p-p66f-jhc7
serveStatic now rejects request paths that still contain % after decoding. To serve files whose names contain a literal %, set allowPercentInPath: true.
The same fix ships in @hono/node-server v2.1.3.
hono/<adapter> still works in v4 but is deprecated and will be removed in v5. Migrating is an import change:
The runtime adapters are now published as their own packages: @hono/bun, @hono/deno, @hono/cloudflare-workers, @hono/aws-lambda, @hono/lambda-edge, @hono/netlify, @hono/vercel, and @hono/service-worker. @hono/deno is also on JSR.
hono/<adapter> still works in v4 but is deprecated and will be removed in v5. Migrating is an import change:
- import { serveStatic } from 'hono/bun'
+ import { serveStatic } from '@hono/bun'hono/cloudflare-pages is deprecated without a replacement package; Cloudflare recommends Workers with static assets.
cr.yml by the pnpm migration in #54561.0.0-rc.1 in #5459adapters/* in #5466Full Changelog: v4.13.9...v4.13.10
fix(jsx): replace Suspense and ErrorBoundary content across newlines in #5380
Full Changelog: v4.13.8...v4.13.9
docs: fix typos in code comments and link third-party middleware section in #5343
Full Changelog: v4.13.7...v4.13.8
This release includes a fix for the following security issue:
This release includes a fix for the following security issue:
hono/jsx renders plain strings unescaped in boundary components, leading to XSSAffects: Suspense, ErrorBoundary, and Context.Provider in hono/jsx, and renderToString() / renderToReadableStream() in hono/jsx/dom/server. Fixes missing HTML escaping for a plain string placed directly as a child or fallback of these components, or as the root value of the server rendering functions, so untrusted strings could be emitted as markup. GHSA-hxh3-vqpv-xpqv
Users who render untrusted strings inside Suspense, ErrorBoundary, or Context.Provider, or pass them directly to hono/jsx/dom/server, are strongly encouraged to upgrade to this version.
fix(client): keep a param value of "index" in $url() and $path() in #5297
editorconfig-checker in #5336Full Changelog: v4.13.5...v4.13.6
Incomplete fix for CVE-2026-39408 : toSSG() still writes files outside the output directory
This release includes fixes for the following security issues:
Affects: Cache Middleware and applications behind a proxy, WAF, or logging layer that inspects query strings. Fixes query parsing that did not stop at the URL fragment, so a ? after a # was treated as the start of a query string and the application could read parameters that the other component never saw. GHSA-crvj-82cr-hjcx
toSSG() still writes files outside the output directoryAffects: toSSG() for Static Site Generation. Fixes a path normalization gap where consecutive parent-directory segments in ssgParams values were not fully collapsed, bypassing the containment check added in 4.12.12. GHSA-gqvv-2mrq-wpjv
parseBody() can cause memory exhaustionAffects: parseBody() when dot-notation parsing is enabled. Fixes unbounded expansion of dot-separated field names, where a small request body could allocate a disproportionately large object graph and concurrent requests could exhaust the heap. GHSA-g6gw-c38x-mqfc
Users who use Cache Middleware, deploy behind a proxy or WAF that inspects query strings, use Static Site Generation, or use parseBody({ dot: true }) are strongly encouraged to upgrade to this version.
fix(request): handle params on unmatched requests in #5268
Full Changelog: v4.13.3...v4.13.4
fix(client): prevent URL corruption when replaceUrlParam contains $ replacement tokens in #5227
Full Changelog: v4.13.2...v4.13.3
fix(secure-headers): output standard empty parentheses () instead of none for disabled Permissions-Policy directives in #5197
Full Changelog: v4.13.1...v4.13.2
fix(trie-router): count every slash a pattern consumes by @Jaybhade in #5189
Full Changelog: v4.13.0...v4.13.1
The highlight of this release is performance: a batch of low-level optimizations makes the core request/response path significantly faster — up to 1.2
Hono v4.13.0 is now available!
The highlight of this release is performance: a batch of low-level optimizations makes the core request/response path significantly faster — up to 1.25x on common routes in our benchmark. This release also adds first-class support for the HTTP QUERY method, defined in RFC 10008, a new Method Not Allowed middleware, and more.
This release includes a series of small optimizations: skipping unnecessary Headers allocations, replacing regex tests with indexOf, allocating internal state lazily, and more.
Here is benchmarks/fetch comparing v4.12 and v4.13 (ROUNDS=5 ./compare.sh, Bun 1.4.0, Apple Silicon — each measurement runs in a fresh process, and the variant order is reversed every round to avoid warm-up bias):
| Benchmark | v4.12 | v4.13 | Speedup |
|---|---|---|---|
ping — GET / |
165.83 ns | 163.99 ns | 1.01x |
query — GET /id/1?name=bun |
674.40 ns | 616.99 ns | 1.09x |
json — GET /user |
528.99 ns | 422.44 ns | 1.25x |
body — POST /json |
1.16 µs | 1.00 µs | 1.15x |
The individual changes:
for..in #5118indexOf #5121Headers creation when there are no headers to merge #5122tryDecodeURIComponent #5158#validatedData lazily #5175In addition, the RegExpRouter rewrite described below makes route registration plus the first match roughly 20% faster.
Thanks @kibertoad for the contributions!
The QUERY method — a safe, idempotent method that carries a request body — is now a first-class citizen in Hono. You can define QUERY handlers with app.query():
const app = new Hono()
app.query('/search', async (c) => {
const conditions = await c.req.json()
return c.json(await search(conditions))
})Thanks @shellhaki!
The built-in middleware has been updated to handle QUERY requests properly:
The Cache Middleware now caches QUERY responses. Following RFC 10008 Section 2.7, the cache key incorporates a SHA-256 digest of the request content and its representation metadata, so different query bodies are cached separately:
app.query(
'/search',
cache({
cacheName: 'search-cache',
cacheControl: 'max-age=3600',
})
)Note: To support this, the internal cache key format has changed for all methods, including GET. Cached entries are now stored under an internal URL of the form /.hono/cache?__hono_cache_key=.... If you purge cache entries by URL outside of the middleware (e.g. calling caches.delete() with the original request URL), you will need to update that logic. Existing cache entries stored with the old format will simply be re-fetched.
The ETag Middleware now handles conditional requests for QUERY, returning 304 Not Modified when If-None-Match matches.
The CORS Middleware now includes QUERY in the default Access-Control-Allow-Methods, which is now GET, HEAD, PUT, POST, DELETE, PATCH, QUERY. If you specify allowMethods explicitly, nothing changes for you.
The new Method Not Allowed Middleware returns a 405 Method Not Allowed response with a proper Allow header when the request path matches a registered route but the method does not:
import { methodNotAllowed } from 'hono/method-not-allowed'
const app = new Hono()
app.use(methodNotAllowed({ app }))
app.get('/hello', (c) => c.text('Hello!'))
app.post('/hello', (c) => c.text('Posted!'))
// PUT /hello -> 405 Method Not Allowed
// Allow: GET, HEAD, POSTYou can customize the response with the onMethodNotAllowed option:
app.use(
methodNotAllowed({
app,
onMethodNotAllowed: (c, methods) =>
c.json({ error: 'Method Not Allowed' }, 405, { Allow: methods.join(', ') }),
})
)Thanks @usualoma!
UnsupportedPathError at registration timeThe RegExpRouter now detects unsupported path combinations when routes are registered, instead of at the first matching request. This means misconfigured routes fail fast at startup rather than at runtime. As a bonus, registration plus the first match is roughly 20% faster.
Thanks @usualoma!
hono/utils/headers has been synced with the IANA HTTP Field Name Registry, adding newly registered fields such as Accept-Query. Thanks @akahoshi1421!realm option for the WWW-Authenticate challenge on 401 responses, and challenge values are properly escaped. Thanks @arhxam!useRef and RefObject are now aligned with React 19. Note that this is a type-level change — RefObject<T> is now { current: T }, so type a nullable ref as RefObject<T | null>, and pass useRef(undefined) instead of useRef(). Thanks @ashunar0!Vary: Accept-Encoding on negotiated responses. Thanks @arhxam!fetch by @yusukebe in #5113indexOf by @yusukebe in #5121tryDecodeURIComponent by @yusukebe in #5158env field initializer by @kibertoad in #5174#validatedData lazily by @kibertoad in #5175fetch by @yusukebe in #5184env field initializer by @yusukebe in #5186Full Changelog: v4.12.34...v4.13.0
Thank you to all contributors!
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
memo() retains SSR output across requests, leading to cross-user data disclosureAffects: hono/jsx (server-side rendering). Fixes memo() reusing a retained render result across requests when props compare equal, where a component reading request-scoped values from ambient context — useContext(), useRequestContext(), or getContext() — could serve HTML rendered for another user's request, disclosing account data or request-scoped secrets such as CSRF tokens. GHSA-f23p-vx2j-j53r
Access-Control-Request-HeadersAffects: hono/cors. Fixes a whitespace-tolerant regular expression with quadratic backtracking used to parse the Access-Control-Request-Headers preflight header when allowHeaders is not configured (the default), where a single preflight request carrying a long whitespace run could consume seconds of CPU and stall request processing. GHSA-8j4g-w8fx-2239
Affects: hono/language. Fixes quadratic string processing in language-tag normalization, where a crafted language tag with a large number of hyphen-separated subtags — supplied via a query parameter, cookie, or Accept-Language header — could cause excessive CPU consumption and block the event loop. GHSA-54fx-42gc-7vw4
Connection headerAffects: hono/proxy. Fixes proxy() forwarding response headers that the origin's Connection header designates as connection-scoped, where headers intended only for the immediate peer — per RFC 9110 Section 7.6.1 — could be exposed to clients, disclosing connection-scoped or internal metadata. GHSA-79qm-7rj5-m7r9
Users who use hono/jsx for server-side rendering, hono/cors, hono/language, or hono/proxy are strongly encouraged to upgrade to this version.
fix(cookie): relax name validation when parsing Cookie header in #5164
@hono/node-server in #5167Full Changelog: v4.12.32...v4.12.33
ci: enable reports for type & bundle size check in #5148
Object.create(null) when parsing query, headers, and params in #5161Full Changelog: v4.12.31...v4.12.32
test(context): assert case-insensitive header names in response helpers by @yusukebe in #5116
@ts-expect-error by @yusukebe in #5130parseBody() by @yusukebe in #5131cloneRawRequest by @yusukebe in #51330 by @yusukebe in #5135Full Changelog: v4.12.30...v4.12.31
chore(benchmark/routers): bump deps in #5107
Full Changelog: v4.12.29...v4.12.30
fix(client): merge function headers with per-request headers by @yusukebe in #5092
compatibilityDate by @yusukebe in #5100* as a match by @yusukebe in #5084Full Changelog: v4.12.28...v4.12.29
fix(serve-static): treat empty string content as found by @yusukebe in https://github.com/honojs/hono/pull/5062
*.tsbuildinfo by @yusukebe in https://github.com/honojs/hono/pull/5066devDependencies by @yusukebe in https://github.com/honojs/hono/pull/5085Full Changelog: https://github.com/honojs/hono/compare/v4.12.27...v4.12.28
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: hono/jsx, hono/jsx-renderer. During SSR, context was stored process-wide instead of per request, so useContext()/useRequestContext() read after an await in an async component could return another concurrent request's value — leading to cross-request data disclosure or authorization checks against the wrong request. GHSA-hvrm-45r6-mjfj
Affects: hono/css. cx() marked its composed class name as already-escaped without escaping the input, so untrusted input passed as a class name could break out of the JSX class attribute during SSR and inject markup (XSS). GHSA-w62v-xxxg-mg59
Affects: hono/aws-lambda. The API Gateway v1 (and VPC Lattice) adapter de-duplicated repeated header values by substring instead of exact match, dropping a value that is a substring of another (e.g. 203.0.113.1 dropped when 203.0.113.10 is present) — affecting logic such as X-Forwarded-For-based IP restriction. GHSA-xgm2-5f3f-mvvc
Users of hono/jsx/hono/jsx-renderer, hono/css (cx()), or the hono/aws-lambda API Gateway v1 / VPC Lattice adapters are encouraged to upgrade.
fix(lambda-edge): satisfy Deno lib types for Content-Length body encoding by @yusukebe in https://github.com/honojs/hono/pull/5013
Full Changelog: https://github.com/honojs/hono/compare/v4.12.25...v4.12.26
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
origin defaults to the wildcardAffects: hono/cors. Fixes the wildcard origin reflecting the request Origin and sending Access-Control-Allow-Credentials: true when credentials: true is set without an explicit origin, where any site a logged-in user visited could make credentialed cross-origin requests and read responses from cookie-authenticated endpoints. GHSA-88fw-hqm2-52qc
Content-LengthAffects: hono/body-limit on AWS Lambda (hono/aws-lambda, hono/lambda-edge). Fixes the request being built with the client-declared Content-Length while the body is delivered fully buffered, where a client could declare a small Content-Length with a much larger body and slip past the configured size limit. GHSA-rv63-4mwf-qqc2
serve-static on Windows via encoded backslash (%5C)Affects: serveStatic on Windows (Node, Bun, Deno adapters). Fixes the path guard allowing a lone backslash, where an encoded backslash (%5C) decoded to \ was treated as a separator by the Windows path resolver, letting a single URL segment escape into a middleware-guarded subtree. GHSA-wwfh-h76j-fc44
Set-Cookie headers into one value, dropping cookies on ALB single-header and LatticeAffects: hono/aws-lambda. Fixes multiple Set-Cookie response headers being joined into one comma-separated value for ALB single-header responses and VPC Lattice v2, where the value could not be split back into individual cookies and clients silently dropped or misparsed them. GHSA-j6c9-x7qj-28xf
Affects: hono/lambda-edge. Fixes repeated request headers being written with overwrite instead of append, where only the last value of a header such as X-Forwarded-For reached the application and the remaining values were silently dropped. GHSA-wgpf-jwqj-8h8p
docs(contribution): simplifyAI Usage Policy by @yusukebe in https://github.com/honojs/hono/pull/4972
Full Changelog: https://github.com/honojs/hono/compare/v4.12.23...v4.12.24
fix(serve-static): normalize all backslashes in file paths, not just the first in https://github.com/honojs/hono/pull/4962
COMPRESSIBLE_CONTENT_TYPE_REGEX re-export by @na-trium-144 in https://github.com/honojs/hono/pull/4961:: by @yusukebe in https://github.com/honojs/hono/pull/4971Full Changelog: https://github.com/honojs/hono/compare/v4.12.22...v4.12.23
chore: update vitest to v4 and cleanups by @BlankParticle in https://github.com/honojs/hono/pull/4952
Full Changelog: https://github.com/honojs/hono/compare/v4.12.21...v4.12.22
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: app.mount(). Fixes prefix stripping using the raw URL pathname instead of the decoded path, where percent-encoded characters in the mount prefix or path could cause the prefix to be removed at the wrong position, resulting in the sub-application receiving an incorrect path. GHSA-2gcr-mfcq-wcc3
Affects: hono/ip-restriction. Fixes IP address comparison using string equality, where non-canonical IPv6 representations of a denied address — such as compressed forms or hex-notation IPv4-mapped addresses — could bypass static deny rules. GHSA-xrhx-7g5j-rcj5
Affects: hono/cookie. Fixes missing validation of sameSite and priority options against injection characters (;, \r, \n), where user-controlled input passed to either option could inject additional attributes into the Set-Cookie response header. GHSA-3hrh-pfw6-9m5x
Affects: hono/jwt, hono/jwk. Fixes missing scheme validation in the Authorization header, where any two-part header value was accepted regardless of the scheme name, allowing non-Bearer schemes to pass JWT authentication. GHSA-f577-qrjj-4474
Users who use app.mount(), hono/ip-restriction, hono/cookie, or hono/jwt/hono/jwk are encouraged to upgrade to this version.
fix(route): preserve the base path of the mounted route() app by @usualoma in https://github.com/honojs/hono/pull/4942
Full Changelog: https://github.com/honojs/hono/compare/v4.12.19...v4.12.20
ci: pin GitHub Actions to SHAs by @yusukebe in https://github.com/honojs/hono/pull/4932
bytes() by @yusukebe in https://github.com/honojs/hono/pull/4921@hono/node-server to v2 and fix abort handling by @yusukebe in https://github.com/honojs/hono/pull/4940Full Changelog: https://github.com/honojs/hono/compare/v4.12.18...v4.12.19
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: Cache Middleware. Fixes missing cache-skip handling for Vary: Authorization and Vary: Cookie, where a response cached for one authenticated user could be served to other users. GHSA-p77w-8qqv-26rm
Affects: hono/jsx. Fixes a missing CSS-context escape for style object values and property names, where untrusted input could inject additional CSS declarations. The impact is limited to CSS and does not allow JavaScript execution. GHSA-qp7p-654g-cw7p
Affects: hono/utils/jwt. Fixes improper validation of exp, nbf, and iat claims, where falsy, non-finite, or non-numeric values could silently bypass time-based checks instead of being rejected per RFC 7519. GHSA-hm8q-7f3q-5f36
Users who use the JWT helper, hono/jsx, or the Cache middleware are strongly encouraged to upgrade to this version.
fix(jsx): normalize SVG attributes on the root element by @kfly8 in https://github.com/honojs/hono/pull/4893
atom+xml and rss+xml to defaultExtensionMap by @yuintei in https://github.com/honojs/hono/pull/4899Full Changelog: https://github.com/honojs/hono/compare/v4.12.16...v4.12.17
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: hono/jsx. Fixes missing validation of JSX tag names when using jsx() or createElement(), which could allow HTML injection if untrusted input is used as the tag name. GHSA-69xw-7hcm-h432
Affects: Body Limit Middleware. Fixes late enforcement for request bodies without a reliable Content-Length (e.g. chunked requests), where oversized requests could reach handlers and return successful responses before being rejected. GHSA-9vqf-7f2p-gf9v
fix(jwt): support single-line PEM keys by @hiendv in https://github.com/honojs/hono/pull/4889
Full Changelog: https://github.com/honojs/hono/compare/v4.12.14...v4.12.15
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: hono/jsx. Fixes missing validation of JSX attribute names during server-side rendering, which could allow malformed attribute keys to corrupt the generated HTML output and inject unintended attributes or elements. GHSA-458j-xx4x-4375
fix(types): infer response type from last handler in app.on 9-/10-handler overloads by @T4ko0522 in https://github.com/honojs/hono/pull/4865
skip option by @yusukebe in https://github.com/honojs/hono/pull/4862onCacheNotAvailable option by @yusukebe in https://github.com/honojs/hono/pull/4876Full Changelog: https://github.com/honojs/hono/compare/v4.12.12...v4.12.13
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: Serve Static middleware. Fixes a path normalization inconsistency where repeated slashes (//) could bypass route-based middleware protections and allow access to protected static files. GHSA-wmmm-f939-6g9c
Affects: toSSG() for Static Site Generation. Fixes a path traversal issue where crafted ssgParams values could write files outside the configured output directory. GHSA-xf4j-xp2r-rqqx
Affects: IP Restriction Middleware. Fixes improper handling of IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1) that could cause allow/deny rules to be bypassed. GHSA-xpcf-pg52-r92g
Affects: setCookie(), serialize(), and serializeSigned() from hono/cookie. Fixes missing validation of cookie names on the write path, preventing inconsistent handling between parsing and serialization. GHSA-26pp-8wgv-hjvm
Affects: getCookie() from hono/cookie. Fixes a discrepancy in cookie name handling that could allow attacker-controlled cookies to override legitimate ones and bypass prefix protections. GHSA-r5rp-j6wh-rvv4
Users who use Serve Static, Static Site Generation, Cookie utilities, or IP restriction middleware are strongly encouraged to upgrade to this version.
feat(css): add classNameSlug option to createCssContext by @flow-pie in https://github.com/honojs/hono/pull/4834
Full Changelog: https://github.com/honojs/hono/compare/v4.12.10...v4.12.11
test(router): fix Simple capturing group test by @yusukebe in https://github.com/honojs/hono/pull/4838
Simple capturing group test by @yusukebe in https://github.com/honojs/hono/pull/4838Full Changelog: https://github.com/honojs/hono/compare/v4.12.9...v4.12.10
fix(request): remove parseBody from bodyCache to prevent TypeError by @yusukebe in https://github.com/honojs/hono/pull/4807
parseBody from bodyCache to prevent TypeError by @yusukebe in https://github.com/honojs/hono/pull/4807PickResponseByStatusCode type by @yusukebe in https://github.com/honojs/hono/pull/4791fire() fallback behavior consistent with handle() by @yusukebe in https://github.com/honojs/hono/pull/4821Full Changelog: https://github.com/honojs/hono/compare/v4.12.8...v4.12.9
fix(utils/mime): Normalize input extension to lowercase before MIME check by @TheEssem in https://github.com/honojs/hono/pull/4800
Full Changelog: https://github.com/honojs/hono/compare/v4.12.7...v4.12.8
Ignore __proto__ path segments in parseBody({ dot: true }) to prevent potential prototype pollution when merged with unsafe patterns.
Ignore __proto__ path segments in parseBody({ dot: true }) to prevent potential prototype pollution when merged with unsafe patterns.
Full Changelog: https://github.com/honojs/hono/compare/v4.12.6...v4.12.7
fix(lambda-edge): avoid callback handler deprecation on NODEJS_24_X by @t0waxx in https://github.com/honojs/hono/pull/4782
tsconfig.spec.json by @yusukebe in https://github.com/honojs/hono/pull/4798Full Changelog: https://github.com/honojs/hono/compare/v4.12.5...v4.12.6
fix(request): return string | undefined from param() when path type is any by @andrewdamelio in https://github.com/honojs/hono/pull/4723
string | undefined from param() when path type is any by @andrewdamelio in https://github.com/honojs/hono/pull/4723@hono/eslint-config by @BarryThePenguin in https://github.com/honojs/hono/pull/4781Full Changelog: https://github.com/honojs/hono/compare/v4.12.4...v4.12.5
This release includes fixes for the following security issues:
This release includes fixes for the following security issues:
Affects: streamSSE() in Streaming Helper. Fixes injection of unintended SSE fields by rejecting CR/LF characters in event, id, and retry. https://github.com/honojs/hono/security/advisories/GHSA-p6xx-57qc-3wxr
setCookie()Affects: setCookie() from hono/cookie. Fixes cookie attribute manipulation by rejecting ;, \r, and \n in domain and path options. https://github.com/honojs/hono/security/advisories/GHSA-5pq2-9x2x-5p6w
Affects: Serve Static middleware. Fixes inconsistent URL decoding that could allow protected static resources to be accessed without triggering route-based middleware. https://github.com/honojs/hono/security/advisories/GHSA-q5qw-h33p-qvwr
Users who uses Strreaming Helper, Cookie utility, and Serve Static are strongly encouraged to upgrade to this version.
tryDecodeURI by @yusukebe in https://github.com/honojs/hono/pull/4779Full Changelog: https://github.com/honojs/hono/compare/v4.12.3...v4.12.4
fix(validator): prevent type diff bug in form data parsing by @EdamAme-x in https://github.com/honojs/hono/pull/4753
Math.floor instead of bitwise OR for safe timestamp by @EdamAme-x in https://github.com/honojs/hono/pull/4754JwtVariables for ContextVariableMap by @yusukebe in https://github.com/honojs/hono/pull/4764Full Changelog: https://github.com/honojs/hono/compare/v4.12.2...v4.12.3
Fixed incorrect handling of X-Forwarded-For in the AWS Lambda adapter behind ALB that could allow IP-based access control bypass. The detail: https://
Fixed incorrect handling of X-Forwarded-For in the AWS Lambda adapter behind ALB that could allow IP-based access control bypass. The detail: https://github.com/honojs/hono/security/advisories/GHSA-xh87-mx6m-69f3
Thanks @EdamAme-x
Full Changelog: https://github.com/honojs/hono/compare/v4.12.1...v4.12.2
fix(client): export ApplyGlobalResponse from hono/client by @sushichan044 in https://github.com/honojs/hono/pull/4743
ApplyGlobalResponse from hono/client by @sushichan044 in https://github.com/honojs/hono/pull/4743Full Changelog: https://github.com/honojs/hono/compare/v4.12.0...v4.12.1
This release includes new features for the Hono client, middleware improvements, adapter enhancements, and significant performance improvements to the
Hono v4.12.0 is now available!
This release includes new features for the Hono client, middleware improvements, adapter enhancements, and significant performance improvements to the router and context.
$path for Hono ClientThe Hono client now has a $path() method that returns the path string instead of a full URL. This is useful when you need just the path portion for routing or key-based operations:
const client = hc<typeof app>('http://localhost:8787')
// Get the path string
const path = client.api.posts.$path()
// => '/api/posts'
// With path parameters
const postPath = client.api.posts[':id'].$path({
param: { id: '123' },
})
// => '/api/posts/123'
// With query parameters
const searchPath = client.api.posts.$path({
query: { filter: 'test' },
})
// => '/api/posts?filter=test'
Unlike $url() which returns a URL object, $path() returns a plain path string, making it convenient for use with routers or as cache keys.
Thanks @ShaMan123!
ApplyGlobalResponse Type Helper for RPC ClientThe new ApplyGlobalResponse type helper allows you to add global error response types to all routes in the RPC client. This is useful for typing common error responses from app.onError() or global middlewares:
const app = new Hono()
.get('/api/users', (c) => c.json({ users: ['alice', 'bob'] }, 200))
.onError((err, c) => c.json({ error: err.message }, 500))
type AppWithErrors = ApplyGlobalResponse<
typeof app,
{
401: { json: { error: string; message: string } }
500: { json: { error: string; message: string } }
}
>
const client = hc<AppWithErrors>('http://api.example.com')
// Now client knows about both success and error responses
const res = await client.api.users.$get()
// InferResponseType includes { users: string[] } | { error: string; message: string }
Thanks @mohankumarelec!
A new redirectPlugin for SSG generates static HTML redirect pages for HTTP redirect responses (301, 302, 303, 307, 308):
import { toSSG } from 'hono/ssg'
import { defaultPlugin, redirectPlugin } from 'hono/ssg'
const app = new Hono()
app.get('/old', (c) => c.redirect('/new'))
app.get('/new', (c) => c.html('New Page'))
// redirectPlugin must be placed before defaultPlugin
await toSSG(app, fs, {
plugins: [redirectPlugin(), defaultPlugin()],
})
The generated redirect pages include a <meta http-equiv="refresh"> tag, a canonical link, and a robots noindex meta tag.
Thanks @3w36zj6!
onAuthSuccess Callback for Basic AuthThe Basic Auth middleware now supports an onAuthSuccess callback that is invoked after successful authentication. This allows you to set context variables or perform logging without re-parsing the Authorization header:
app.use(
'/auth/*',
basicAuth({
username: 'hono',
password: 'ahotproject',
onAuthSuccess: (c, username) => {
c.set('user', { name: username, role: 'admin' })
console.log(`User ${username} authenticated`)
},
})
)
The callback also works with async functions and the verifyUser mode.
Thanks @AprilNEA!
getConnInfo for AWS Lambda, Cloudflare Pages, and NetlifygetConnInfo() is now available for three additional adapters:
// AWS Lambda (supports API Gateway v1, v2, and ALB)
import { handle, getConnInfo } from 'hono/aws-lambda'
// Cloudflare Pages
import { handle, getConnInfo } from 'hono/cloudflare-pages'
// Netlify
import { handle, getConnInfo } from 'hono/netlify'
app.get('/', (c) => {
const info = getConnInfo(c)
return c.text(`Your IP: ${info.remote.address}`)
})
Thanks @rokasta12!
alwaysRedirect Option for Trailing Slash MiddlewareThe trailing slash middleware now supports an alwaysRedirect option. When enabled, the middleware redirects before executing handlers, which fixes the issue where trailing slash handling doesn't work with wildcard routes:
app.use(trimTrailingSlash({ alwaysRedirect: true }))
app.get('/my-path/*', async (c) => {
return c.text('wildcard')
})
// /my-path/something/ will be redirected to /my-path/something
// before the wildcard handler is executed
The normalizeLanguage function in the language middleware now supports RFC 4647 Lookup-based progressive truncation. Locale codes like ja-JP will match ja when only the base language is in supportedLanguages:
app.use(
'/*',
languageDetector({
supportedLanguages: ['en', 'ja'],
fallbackLanguage: 'en',
order: ['cookie', 'header'],
})
)
// Accept-Language: ja-JP → matches 'ja'
// Accept-Language: ko-KR → falls back to 'en'
Thanks @sorafujitani!
exports Field for ExecutionContextThe ExecutionContext type now includes an exports property for Cloudflare Workers. You can use module augmentation to type it with Wrangler's generated types:
import 'hono'
declare module 'hono' {
interface ExecutionContext {
readonly exports: Cloudflare.Exports
}
}
Thanks @toreis-up!
The TrieRouter has been significantly optimized with reduced spread syntax usage, O(1) hasChildren checks, lazy regular expression generation, and removal of redundant processes:
| Route | Node.js | Deno | Bun |
|---|---|---|---|
short static GET /user |
1.70x | 1.40x | 1.34x |
dynamic GET /user/lookup/username/hey |
1.38x | 1.69x | 1.51x |
wildcard GET /static/index.html |
1.51x | 1.72x | 1.43x |
| all together | 1.58x | 1.60x | 1.82x |
Thanks @EdamAme-x!
c.json()c.json() now has the same fast path optimization as c.text(). When no custom status, headers, or finalized state exists, the Response is created directly without allocating a Headers object:
// This common pattern is now faster
return c.json({ message: 'Hello' })
Benchmark results:
| Metric | Before | After | Change |
|---|---|---|---|
| Reqs/sec | 92,268 | 95,244 | +3.2% |
| Latency | 5.42ms | 5.25ms | -3.1% |
| Throughput | 17.24MB/s | 19.07MB/s | +10.6% |
Thanks @mgcrea!
ApplyGlobalResponse type helper for RPC Client https://github.com/honojs/hono/pull/4556alwaysRedirect option to support wildcard routes https://github.com/honojs/hono/pull/4658createResponseInstance for new Response https://github.com/honojs/hono/pull/4733ApplyGlobalResponse type helper for RPC Client by @mohankumarelec in https://github.com/honojs/hono/pull/4556alwaysRedirect option to support wildcard routes by @yusukebe in https://github.com/honojs/hono/pull/4658createResponseInstance for new Response by @yusukebe in https://github.com/honojs/hono/pull/4733Full Changelog: https://github.com/honojs/hono/compare/v4.11.10...v4.12.0
fix: fixed to be more properly timing safe (Merge commit from fork 91def7ca)
Full Changelog: https://github.com/honojs/hono/compare/v4.11.9...v4.11.10
fix(url): ignore fragment identifiers in getPath() by @sano-suguru in https://github.com/honojs/hono/pull/4627
node.vC[0] instead of referring to node.pP by @usualoma in https://github.com/honojs/hono/pull/4663Full Changelog: https://github.com/honojs/hono/compare/v4.11.8...v4.11.9
fix(jsx): preserve context when using await before html helper by @kaigritun in https://github.com/honojs/hono/pull/4662
Full Changelog: https://github.com/honojs/hono/compare/v4.11.7...v4.11.8
This release includes security fixes for multiple vulnerabilities in Hono and related middleware. We recommend upgrading if you are using any of the a…
This release includes security fixes for multiple vulnerabilities in Hono and related middleware. We recommend upgrading if you are using any of the affected components.
Fixed an IPv4 address validation bypass that could allow IP-based access control to be bypassed under certain configurations.
Fixed an issue where responses marked with Cache-Control: private or no-store could be cached, potentially leading to information disclosure on some runtimes.
Fixed an issue that could allow unintended access to internal asset keys when serving static files with user-controlled paths.
ErrorBoundaryFixed a reflected Cross-Site Scripting (XSS) issue in the ErrorBoundary component that could occur when untrusted strings were rendered without proper escaping.
Users are encouraged to upgrade to this release, especially if they:
ErrorBoundary componentsIP Restriction Middleware – IPv4 address validation bypass
Cache Middleware ignores Cache-Control: private
Serve Static Middleware (Cloudflare Workers adapter) – Arbitrary key read
hono/jsx ErrorBoundary – Cross-Site Scripting (XSS)
Full Changelog: https://github.com/honojs/hono/compare/v4.11.6...v4.11.7
refactor: use unique symbol for more accurate typing. by @usualoma in https://github.com/honojs/hono/pull/4651
unique symbol for more accurate typing. by @usualoma in https://github.com/honojs/hono/pull/4651\r and \r\n line endings in writeSSE by @AprilNEA in https://github.com/honojs/hono/pull/4644Full Changelog: https://github.com/honojs/hono/compare/v4.11.5...v4.11.6
fix(client): exclude $all from ClientRequest type by @paveg in https://github.com/honojs/hono/pull/4611
AlgorithmTypes by @yusukebe in https://github.com/honojs/hono/pull/4642Full Changelog: https://github.com/honojs/hono/compare/v4.11.4...v4.11.5
docs(bun/websocket): Fixed a typo in hono/bun deprecation message and updated test. by @Itsnotaka in https://github.com/honojs/hono/pull/4618
Fixed a JWT algorithm confusion issue in the JWT and JWK/JWKS middleware.
Both middlewares now require an explicit algorithm configuration to prevent the verification algorithm from being influenced by untrusted JWT header values.
If you are using the JWT or JWK/JWKS middleware, please update to the latest version as soon as possible.
import { jwt } from 'hono/jwt'
app.use(
'/auth/*',
jwt({
secret: 'it-is-very-secret',
alg: 'HS256', // required
})
)
import { jwk } from 'hono/jwk'
app.use(
'/auth/*',
jwk({
jwks_uri: 'https://example.com/.well-known/jwks.json',
alg: ['RS256'], // required (asymmetric algorithms only)
})
)
For more details, see the Security Advisory.
@hono/eslint-config and enable curly rule by @yusukebe in https://github.com/honojs/hono/pull/4620alg option for JWT middleware by @yusukebe in https://github.com/honojs/hono/pull/4624Full Changelog: https://github.com/honojs/hono/compare/v4.11.3...v4.11.4
fix(types): fix middleware union type merging in MergeMiddlewareResponse by @yusukebe in https://github.com/honojs/hono/pull/4602
Full Changelog: https://github.com/honojs/hono/compare/v4.11.2...v4.11.3
docs: improve grammar in contributing documentation by @Ishiezz in https://github.com/honojs/hono/pull/4581
HonoURL types by @yusukebe in https://github.com/honojs/hono/pull/4592Simplify in ToSchema by @yusukebe in https://github.com/honojs/hono/pull/4597MergeMiddlewareResponse type by @yusukebe in https://github.com/honojs/hono/pull/4598Full Changelog: https://github.com/honojs/hono/compare/v4.11.1...v4.11.2
fix(types): fix app.on method array type inference by @kosei28 in https://github.com/honojs/hono/pull/4578
Full Changelog: https://github.com/honojs/hono/compare/v4.11.0...v4.11.1
This release includes new features for the Hono client, middleware improvements, and an important type system fix.
Hono v4.11.0 is now available!
This release includes new features for the Hono client, middleware improvements, and an important type system fix.
We've fixed a bug in the type system for middleware. Previously, app did not have the correct type with pathless handlers:
const app = new Hono()
.use(async (c, next) => {
await next()
})
.get('/a', async (c, next) => {
await next()
})
.get((c) => {
return c.text('Hello')
})
// app's type was incorrect
This has now been fixed.
Thanks @kosei28!
You can now pass the base URL as the second type parameter to hc to get more precise URL types:
const client = hc<typeof app, 'http://localhost:8787'>(
'http://localhost:8787/'
)
const url = client.api.posts.$url()
// url is TypedURL with precise type information
// including protocol, host, and path
This is useful when you want to use the URL as a type-safe key for libraries like SWR.
Thanks @miyaji255!
You can now customize the NotFoundResponse type using module augmentation. This allows c.notFound() to return a typed response:
import { Hono, TypedResponse } from 'hono'
declare module 'hono' {
interface NotFoundResponse
extends Response,
TypedResponse<{ error: string }, 404, 'json'> {}
}
const app = new Hono()
.get('/posts/:id', async (c) => {
const post = await getPost(c.req.param('id'))
if (!post) {
return c.notFound()
}
return c.json({ post }, 200)
})
.notFound((c) => c.json({ error: 'not found' }, 404))
Now the client can correctly infer the 404 response type.
Thanks @miyaji255!
The new tryGetContext() helper in the Context Storage middleware returns undefined instead of throwing an error when the context is not available:
import { tryGetContext } from 'hono/context-storage'
const context = tryGetContext<Env>()
if (context) {
// Context is available
console.log(context.var.message)
}
Thanks @AyushCoder9!
You can now customize how query parameters are serialized using the buildSearchParams option:
const client = hc<AppType>('http://localhost', {
buildSearchParams: (query) => {
const searchParams = new URLSearchParams()
for (const [k, v] of Object.entries(query)) {
if (v === undefined) continue
if (Array.isArray(v)) {
v.forEach((item) => searchParams.append(`${k}[]`, item))
} else {
searchParams.set(k, v)
}
}
return searchParams
},
})
Thanks @bolasblack!
Full Changelog: https://github.com/honojs/hono/compare/v4.10.8...v4.11.0
Your coding agent can read these notes before it upgrades. Set up the MCP server →