Skip to Content
referenceBuilt In Middleware

Last Updated: 3/11/2026


Built-in Middleware

Hono includes powerful middleware for common tasks like authentication, CORS, logging, and security.

Authentication

Basic Auth

HTTP Basic Authentication:

import { basicAuth } from 'hono/basic-auth' app.use( '/admin/*', basicAuth({ username: 'admin', password: 'secret', }) ) app.get('/admin', (c) => c.text('Admin panel'))

With environment variables:

app.use('/admin/*', async (c, next) => { const auth = basicAuth({ username: c.env.USERNAME, password: c.env.PASSWORD, }) return auth(c, next) })

Bearer Auth

Token-based authentication:

import { bearerAuth } from 'hono/bearer-auth' app.use( '/api/*', bearerAuth({ token: 'your-secret-token', }) )

With custom verification:

app.use( '/api/*', bearerAuth({ verifyToken: async (token, c) => { return token === await c.env.DB.getToken() }, }) )

JWT Auth

JSON Web Token authentication:

import { jwt } from 'hono/jwt' app.use( '/protected/*', jwt({ secret: 'your-secret-key', }) ) app.get('/protected/data', (c) => { const payload = c.get('jwtPayload') return c.json({ user: payload }) })

With algorithm:

app.use( '/protected/*', jwt({ secret: 'your-secret-key', alg: 'HS256', }) )

CORS

Handle Cross-Origin Resource Sharing:

import { cors } from 'hono/cors' // Default (allow all origins) app.use('/api/*', cors()) // With options app.use( '/api/*', cors({ origin: 'https://example.com', allowMethods: ['GET', 'POST', 'PUT', 'DELETE'], allowHeaders: ['Content-Type', 'Authorization'], exposeHeaders: ['X-Total-Count'], credentials: true, maxAge: 600, }) ) // Multiple origins app.use( '/api/*', cors({ origin: ['https://example.com', 'https://app.example.com'], }) ) // Dynamic origin app.use( '/api/*', cors({ origin: (origin) => { return origin.endsWith('.example.com') ? origin : 'https://example.com' }, }) )

Logger

Log requests:

import { logger } from 'hono/logger' app.use(logger()) // Custom format app.use( logger((str, ...rest) => { console.log(`[Custom] ${str}`, ...rest) }) )

Security

Secure Headers

Add security headers:

import { secureHeaders } from 'hono/secure-headers' app.use(secureHeaders()) // Custom options app.use( secureHeaders({ contentSecurityPolicy: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'"], }, xFrameOptions: 'DENY', xContentTypeOptions: 'nosniff', }) )

CSRF Protection

Prevent Cross-Site Request Forgery:

import { csrf } from 'hono/csrf' app.use(csrf()) // With options app.use( csrf({ origin: 'https://example.com', }) )

Caching

ETag

Add ETag headers:

import { etag } from 'hono/etag' app.use(etag()) // With options app.use( etag({ weak: true, }) )

Cache

Cache responses:

import { cache } from 'hono/cache' app.use( '*', cache({ cacheName: 'my-app', cacheControl: 'max-age=3600', }) )

Compression

Compress responses:

import { compress } from 'hono/compress' app.use(compress()) // With options app.use( compress({ encoding: 'gzip', }) )

Body Limit

Limit request body size:

import { bodyLimit } from 'hono/body-limit' app.use( '/upload', bodyLimit({ maxSize: 1024 * 1024, // 1MB onError: (c) => { return c.text('Payload too large', 413) }, }) )

Pretty JSON

Format JSON responses:

import { prettyJSON } from 'hono/pretty-json' app.use(prettyJSON()) // Only in development if (process.env.NODE_ENV === 'development') { app.use(prettyJSON()) }

Request ID

Add unique request IDs:

import { requestId } from 'hono/request-id' app.use(requestId()) app.get('/', (c) => { const id = c.get('requestId') return c.json({ requestId: id }) }) // Custom generator app.use( requestId({ generator: () => crypto.randomUUID(), }) )

Timeout

Timeout long-running requests:

import { timeout } from 'hono/timeout' app.use( '/api/*', timeout(5000) // 5 seconds ) // With custom handler app.use( '/api/*', timeout(5000, (c) => { return c.json({ error: 'Request timeout' }, 504) }) )

Timing

Add Server-Timing headers:

import { timing } from 'hono/timing' app.use(timing()) app.get('/data', async (c) => { const start = Date.now() const data = await fetchData() c.res.headers.append('Server-Timing', `db;dur=${Date.now() - start}`) return c.json(data) })

Method Override

Override HTTP methods:

import { methodOverride } from 'hono/method-override' app.use(methodOverride()) // Now POST with _method=DELETE works as DELETE

Trailing Slash

Handle trailing slashes:

import { trimTrailingSlash } from 'hono/trailing-slash' app.use(trimTrailingSlash()) // /path/ redirects to /path

IP Restriction

Restrict access by IP:

import { ipRestriction } from 'hono/ip-restriction' app.use( '/admin/*', ipRestriction(getConnInfo, { allowList: ['192.168.1.1', '10.0.0.0/8'], }) )

JSX Renderer

Render JSX with layouts:

import { jsxRenderer } from 'hono/jsx-renderer' app.use( '*', jsxRenderer(({ children }) => { return ( <html> <body> <header>My Site</header> {children} <footer>© 2024</footer> </body> </html> ) }) ) app.get('/', (c) => { return c.render(<h1>Hello!</h1>) })

Combine

Combine multiple middleware:

import { combine } from 'hono/combine' import { logger } from 'hono/logger' import { cors } from 'hono/cors' const middleware = combine(logger(), cors()) app.use('/api/*', middleware)

Next Steps

You’ve completed the critical path! Explore more topics:

  • JSX - Build UIs with JSX
  • SSG - Static site generation
  • Examples  - Real-world examples