Skip to content

v4.5.0

Compare
Choose a tag to compare
@yusukebe yusukebe released this 16 Jul 14:23
· 214 commits to main since this release

Hono v4.5.0 is now available!

We have added three new built-in middleware. Now Hono is bringing 20 built-in middleware!

  1. Basic Authentication
  2. Bearer Authentication
  3. Body Limit
  4. Cache
  5. Combine
  6. Compress
  7. CORS
  8. CSRF Protection
  9. ETag
  10. IP Restriction
  11. JSX Renderer
  12. JWT
  13. Logger
  14. Method Override
  15. Pretty JSON
  16. Request ID
  17. Secure Headers
  18. Timeout
  19. Timing
  20. Trailing Slash

Amazing! These truly make Hono batteries-included framework.

Let's go through the new features in this release.

IP Restrict Middleware

Introducing IP Restrict Middleware. This middleware limits access to resources based on the IP address of the user.

import { Hono } from 'hono'
import { getConnInfo } from 'hono/bun'
import { ipRestriction } from 'hono/ip-restriction'

const app = new Hono()

app.use(
  '*',
  ipRestriction(getConnInfo, {
    denyList: [],
    allowList: ['127.0.0.1', '::1']
  })
)

Thanks @nakasyou!

Combine Middleware

Introducing Combine Middleware. This middleware combines multiple middleware functions into a single middleware, allowing you to create complex access controls by combining it with middleware like IP Restriction.

import { Hono } from 'hono'
import { bearerAuth } from 'hono/bearer-auth'
import { getConnInfo } from 'hono/cloudflare-workers'
import { every, some } from 'hono/combine'
import { ipRestriction } from 'hono/ip-restriction'
import { rateLimit } from '@/my-rate-limit'

const app = new Hono()

app.use(
  '*',
  some(
    every(ipRestriction(getConnInfo, { allowList: ['192.168.0.2'] }), bearerAuth({ token })),
    // If both conditions are met, rateLimit will not execute.
    rateLimit()
  )
)

app.get('/', (c) => c.text('Hello Hono!'))

Thanks @usualoma!

Request ID Middleware

Introducing Request ID Middleware. This middleware generates a unique ID for each request, which you can use in your handlers.

import { Hono } from 'hono'
import { requestId } from 'hono/request-id'

const app = new Hono()

app.use('*', requestId())

app.get('/', (c) => {
  return c.text(`Your request id is ${c.get('requestId')}`)
})

Thanks @ryuapp!

Service Worker Adapter

A Service Worker adapter has been added, making it easier to run Hono applications as Service Workers.

For example, the following code works perfectly in a browser!

import { Hono } from 'hono'
import { handle } from 'hono/service-worker'

const app = new Hono().basePath('/sw')
app.get('/', (c) => c.text('Hello World'))

self.addEventListener('fetch', handle(app))

Thanks @nakasyou!

Cloudflare Pages Middleware

The Cloudflare Pages adapter now includes a handleMiddleware function, allowing many Hono middleware to run as Cloudflare Pages middleware.

For example, to apply basic authentication, you can use the built-in middleware as shown below.

// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
import { basicAuth } from 'hono/basic-auth'

export const onRequest = handleMiddleware(
  basicAuth({
    username: 'hono',
    password: 'acoolproject'
  })
)

Thanks @BarryThePenguin!

React 19 Compatibility

Hono JSX now supports React 19 compatible APIs.

For example, the following hooks have been added:

  • useFormStatus()
  • useActionState()
  • useOptimistic()

Additionally, rendering metadata within the <head /> tag is now supported. You can include elements like <title>, <meta>, and <link> within your components.

import { Hono } from 'hono'
import { jsxRenderer } from 'hono/jsx-renderer'

const app = new Hono()

app.use(
  jsxRenderer(({ children }) => {
    return (
      <html>
        <head></head>
        <body>{children}</body>
      </html>
    )
  })
)

app.get('/top-page', (c) => {
  return c.render(
    <article>
      <title>Top Page!</title>
      <link rel="canonical" href="https://hono.dev/top-page" />
      <h1>Top Page</h1>
      <p>Hono is a great framework!</p>
    </article>
  )
})

The above will render the following HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Top Page!</title>
    <link rel="canonical" href="https://hono.dev/top-page" />
  </head>
  <body>
    <article>
      <h1>Top Page</h1>
      <p>Hono is a great framework!</p>
    </article>
  </body>
</html>

See all changes in this PR: #2960

Thanks @usualoma!

@hono/react-compat

Plus, with the new @hono/react-compat, you can alias the react or react-dom used in your project to hono/jsx without any configuration.

npm install react@npm:@hono/react-compat react-dom@npm:@hono/react-compat

Passing interface as Bindings/Variables

You can now pass interface to Bindings or Variables. This allows you to use the type definitions generated by the wrangler types command directly.

interface Env {
  MY_KV_NAMESPACE: KVNamespace
  MY_VAR: string
  MY_DB: D1Database
}

Previously, only type definitions using type could be passed to Bindings. Now, interfaces like the Env example above can be used with generics.

const app = new Hono<{
  Bindings: Env
}>()

Thanks @ottomated!

Other features

  • JWT - use Signed Cookie in JWT Middleware #2989
  • Vercel - add getConnInfo for Vercel Adapter #3085
  • Lambda@Edge - add getConnInfo helper for Lambda@Edge #3099

All Updates

New Contributors

Full Changelog: v4.4.13...v4.5.0