v4.7.0
honojs/honov4.7.0Feb 7, 2025by yusukebe
AI Summary
Hono v4.7.0 introduces a Proxy Helper for proper reverse proxy handling (solving Accept-Encoding and Transfer-Encoding header issues), a Language Middleware for i18n with detection from query params/cookies/headers/URL path, and JWK Auth Middleware for JSON Web Key authentication. Additionally, Standard Schema Validator provides a unified interface for Zod, Valibot, and ArkType validators.
Key Highlights
- Proxy Helper - solves header issues when using Hono as a reverse proxy by properly handling Accept-Encoding and Transfer-Encoding
- Language Middleware - provides i18n functions with language detection from query params, cookies, Accept-Language header, or URL path
- JWK Auth Middleware - authenticates requests using JSON Web Keys fetched from a specified JWKS URL
- Standard Schema Validator - unified validator interface supporting Zod, Valibot, and ArkType with the same code
- Logger now includes query parameters in output
New Features
- Proxy Helper - handles reverse proxy requests with proper header management
- Language Middleware - i18n support with languageDetector function
- JWK Auth Middleware - JWT authentication using JSON Web Keys
- Standard Schema Validator - unified validation interface for multiple validator libraries
- Logger includes query params in output
- Context buffer returns support
- ETag allows custom hashing methods
- Router supports greedy matches with subsequent static components
- Factory allows HonoOptions<E> configuration
Full Release Notes
# Release Notes
Hono v4.7.0 is now available!
This release introduces one helper and two middleware.
- Proxy Helper
- Language Middleware
- JWK Auth Middleware
Plus, Standard Schema Validator has been born.
Let's look at each of these.
## Proxy Helper
We sometimes use the Hono application as a reverse proxy. In that case, it accesses the backend using `fetch`. However, it sends an unintended headers.
```ts
app.all('/proxy/:path', (c) => {
// Send unintended header values to the origin server
return fetch(`http://${originServer}/${c.req.param('path')}`)
})
```
For example, `fetch` may send `Accept-Encoding`, causing the origin server to return a compressed response. Some runtimes automatically decode it, leading to a `Content-Length` mismatch and potential client-side errors.
Also, you should probably remove some of the headers sent from the origin server, such as `Transfer-Encoding`.
[Proxy Helper](https://hono.dev/docs/helpers/proxy) will send requests to the origin and handle responses properly. The above headers problem is solved simply by writing as follows.
```ts
import { Hono } from 'hono'
import { proxy } from 'hono/proxy'
app.get('/proxy/:path', (c) => {
return proxy(`http://${originServer}/${c.req.param('path')}`)
})
```
You can also use it in more complex ways.
```ts
app.get('/proxy/:path', async (c) => {
const res = await proxy(
`http://${originServer}/${c.req.param('path')}`,
{
headers: {
...c.req.header(),
'X-Forwarded-For': '127.0.0.1',
'X-Forwarded-Host': c.req.header('host'),
Authorization: undefined,
},
}
)
res.headers.delete('Set-Cookie')
return res
})
```
Thanks @usualoma!
## Language Middleware
[Language Middleware](https://hono.dev/docs/middleware/builtin/language) provides 18n functions to Hono applications. By using the `languageDetector` function, you can get the language that your application should support.
```ts
import { Hono } from 'hono'
import { languageDetector } from 'hono/language'
const app = new Hono()
app.use(
languageDetector({
supportedLanguages: ['en', 'ar', 'ja'], // Must include fallback
fallbackLanguage: 'en', // Required
})
)
app.get('/', (c) => {
const lang = c.get('language')
return c.text(`Hello! Your language is ${lang}`)
})
```
You can get the target language in various ways, not just by using `Accept-Language`.
- Query parameters
- Cookies
- `Accept-Language` header
- URL path
Thanks @lord007tn!
## JWK Auth Middleware
Finally, middleware that supports JWK (JSON Web Key) has landed. Using [JWK Auth Middleware](https://hono.dev/docs/middleware/builtin/jwk), you can authenticate by verifying JWK tokens. It can access keys fetched from the specified URL.
```ts
import { Hono } from 'hono'
import { jwk } from 'hono/jwk'
app.use(
'/auth/*',
jwk({
jwks_uri: `https://${backendServer}/.well-known/jwks.json`,
})
)
app.get('/auth/page', (c) => {
return c.text('You are authorized')
})
```
Thanks @Beyondo!
## Standard Schema Validator
[Standard Schema](https://standardschema.dev/) provides a common interface for TypeScript validator libraries. [Standard Schema Validator](https://github.com/honojs/middleware/tree/main/packages/standard-validator) is a validator that uses it. This means that Standard Schema Validator can handle several validators, such as Zod, Valibot, and ArkType, with the same interface.
The code below really works!
```ts
import { Hono } from 'hono'
import { sValidator } from '@hono/standard-validator'
import { type } from 'arktype'
import * as v from 'valibot'
import { z } from 'zod'
const aSchema = type({
agent: 'string',
})
const vSchema = v.object({
slag: v.string(),
})
const zSchema = z.object({
name: z.string(),
})
const app = new Hono()
app.get(
'/:slag',
sValidator('header', aSchema),
sValidator('param', vSchema),
sValidator('query', zSchema),
(c) => {
const headerValue = c.req.valid('header')
const paramValue = c.req.valid('param')
const queryValue = c.req.valid('query')
return c.json({ headerValue, paramValue, queryValue })
}
)
const res = await app.request('/foo?name=foo', {
headers: {
agent: 'foo',
},
})
console.log(await res.json())
```
Thanks @muningis!
## New features
- feat(helper/proxy): introduce proxy helper https://github.com/honojs/hono/pull/3589
- feat(logger): include query params https://github.com/honojs/hono/pull/3702
- feat: add language detector middleware and helpers https://github.com/honojs/hono/pull/3787
- feat(hono/context): add buffer returns https://github.com/honojs/hono/pull/3813
- feat(hono/jwk): JWK Auth Middleware https://github.com/honojs/hono/pull/3826
- feat(etag): allow for custom hashing methods to be used to etag https://github.com/honojs/hono/pull/3832
- feat(router): support greedy matches with subsequent static components https://github.com/honojs/hono/pull/3888
## All changes
- docs(CONTRIBUTING): remove text about `yarn` by @EdamAme-x in https://github.com/honojs/hono/pull/3878
- refactor(request): `toLowerCase()` is unnecessary for `req.header()` by @yusukebe in https://github.com/honojs/hono/pull/3880
- fix(helper/adapter): correct `env` type by @yusukebe in https://github.com/honojs/hono/pull/3885
- chore(test): update to vitest 3 by @yasuaki640 in https://github.com/honojs/hono/pull/3861
- fix(router/trie-router): fix label with trailing wildcard pattern by @usualoma in https://github.com/honojs/hono/pull/3892
- feat(helper/proxy): introduce proxy helper by @usualoma in https://github.com/honojs/hono/pull/3589
- feat(logger): include query params by @ryuapp in https://github.com/honojs/hono/pull/3702
- feat(factory): Allow HonoOptions<E> with factory by @miyaji255 in https://github.com/honojs/hono/pull/3786
- feat: add language detector middleware and helpers by @lord007tn in https://github.com/honojs/hono/pull/3787
- feat(hono/context): add buffer returns by @askorupskyy in https://github.com/honojs/hono/pull/3813
- feat(hono/jwk): JWK Auth Middleware by @Beyondo in https://github.com/honojs/hono/pull/3826
- feat(etag): allow for custom hashing methods to be used to etag by @EdamAme-x in https://github.com/honojs/hono/pull/3832
- feat(router): support greedy matches with subsequent static components. by @usualoma in https://github.com/honojs/hono/pull/3888
- fix(client): correct inferring empty object from`c.json({})` by @yusukebe in https://github.com/honojs/hono/pull/3873
- Next by @yusukebe in https://github.com/honojs/hono/pull/3896
- chore(runtime-tests): add `deno.lock` by @yusukebe in https://github.com/honojs/hono/pull/3897
## New Contributors
- @lord007tn made their first contribution in https://github.com/honojs/hono/pull/3787
**Full Changelog**: https://github.com/honojs/hono/compare/v4.6.20...v4.7.0