compress middleware encoding option
The optional 'encoding' option accepts 'gzip' or 'deflate' to specify the compression scheme. If not defined, both are allowed and will be used based on the Accept-Encoding header. gzip is prioritized if the option is not provided and the client provides both.
compress middleware contentTypeFilter example with function
Example showing how to use compress middleware with a function to extend default behavior:
import { compress, COMPRESSIBLE_CONTENT_TYPE_REGEX } from 'hono/compress'
app.use(
compress({
contentTypeFilter: (type) =>
COMPRESSIBLE_CONTENT_TYPE_REGEX.test(type) ||
type === 'application/x-myformat',
})
)
This compresses the default Content-Types plus a custom one ('application/x-myformat').
compress middleware contentTypeFilter example with RegExp
Example showing how to use compress middleware with a RegExp to compress only JSON responses: app.use(compress({ contentTypeFilter: /^application\/json/ }))
compress middleware contentTypeFilter option
The optional 'contentTypeFilter' option accepts either a RegExp or a function (contentType: string) => boolean to determine whether the response should be compressed based on its Content-Type. By default, a built-in list of compressible Content-Types is used. A RegExp can be passed to compress only matching Content-Types, or a function can be passed for custom logic. The built-in COMPRESSIBLE_CONTENT_TYPE_REGEX is exported from 'hono/compress' to allow extending the default behavior.
compress middleware threshold option
The optional 'threshold' option is a number specifying the minimum size in bytes to compress. It defaults to 1024 bytes.
compress middleware not needed on Cloudflare Workers and Deno Deploy
On Cloudflare Workers and Deno Deploy, the response body is compressed automatically, so the compress middleware does not need to be used.
compress middleware import and basic usage
The compress middleware is imported from 'hono/compress'. It compresses the response body according to the Accept-Encoding request header. Basic usage: app.use(compress()).
Context Storage Middleware imports
The Context Storage Middleware is imported from 'hono/context-storage'. The import includes three exports: contextStorage, getContext, and tryGetContext.
contextStorage middleware stores Context in AsyncLocalStorage
The contextStorage() middleware stores the Hono Context in AsyncLocalStorage to make it globally accessible. This requires the runtime to support AsyncLocalStorage.
Context Storage Middleware example with Cloudflare bindings
On Cloudflare Workers, bindings defined in the Env type can be accessed outside the handler after applying contextStorage(). Example: getContext<Env>().env.KV allows access to a KV namespace binding globally.
Context Storage Middleware example with variables
Example showing context storage usage: call app.use(contextStorage()) first, then variables set via c.set('message', 'Hello!') can be accessed globally outside the handler using getContext<Env>().var.message.
tryGetContext() safe alternative to getContext()
The tryGetContext() function works like getContext() but returns undefined instead of throwing an error when the context is not available. It is generic and accepts a type parameter for the Env type.
getContext() returns current Context object
The getContext() function returns the current Context object when contextStorage() middleware is applied. It is generic and accepts a type parameter for the Env type. Calling getContext() outside of a handler allows access to context variables and bindings that were set in middleware.
CORS with Vite configuration
When using Hono with Vite, disable Vite's built-in CORS feature by setting server.cors to false in vite.config.ts to prevent conflicts with Hono's CORS middleware.
CORS origin option
The origin option sets the Access-Control-Allow-Origin header. It accepts a string, array of strings, or a callback function that receives the origin and Context object. The default value is '*'. When using a callback, return the origin to allow it or an alternative origin string.
CORS with dynamic origin callback example
Use a callback function to dynamically determine allowed origins based on the request origin: cors({ origin: (origin, c) => { return origin.endsWith('.example.com') ? origin : 'http://example.com' } })
CORS configuration from environment variables
To adjust CORS configuration based on execution environment (development/production), use environment variables within middleware: app.use('*', async (c, next) => { const corsMiddlewareHandler = cors({ origin: c.env.CORS_ORIGIN }); return corsMiddlewareHandler(c, next); })
CORS with dynamic allowMethods callback example
Use a callback function to dynamically determine allowed methods based on the origin: cors({ origin: (origin) => origin === 'https://example.com' ? origin : '*', allowMethods: (origin, c) => origin === 'https://example.com' ? ['GET', 'HEAD', 'POST', 'PATCH', 'DELETE'] : ['GET', 'HEAD'] })
CORS with multiple origins example
The origin option accepts an array of strings to allow multiple origins: cors({ origin: ['https://example.com', 'https://example.org'] })
CORS exposeHeaders option
The exposeHeaders option sets the Access-Control-Expose-Headers header. It accepts an array of header names as strings that should be exposed to the browser. The default is an empty array [].
CORS credentials option
The credentials option is a boolean that sets the Access-Control-Allow-Credentials header, indicating whether credentials can be included in CORS requests.
CORS maxAge option
The maxAge option sets the Access-Control-Max-Age header as a number, specifying how long preflight responses can be cached in seconds.
CORS allowHeaders option
The allowHeaders option sets the Access-Control-Allow-Headers header. It accepts an array of header names as strings. The default is an empty array [].
CORS allowMethods option
The allowMethods option sets the Access-Control-Allow-Methods header. It accepts an array of HTTP method strings or a callback function that receives origin and Context object to dynamically determine allowed methods. The default is ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'QUERY'].
CORS middleware options reference
The CORS middleware accepts the following optional options: origin (string | string[] | (origin:string, c:Context) => string), allowMethods (string[] | (origin:string, c:Context) => string[]), allowHeaders (string[]), maxAge (number), credentials (boolean), and exposeHeaders (string[]).
CORS middleware basic usage
The CORS middleware is called with app.use() before route handlers. It should be applied to routes using a path pattern such as app.use('/api/*', cors()).
CORS middleware import
Import the CORS middleware from 'hono/cors' using: import { cors } from 'hono/cors'
CSRF middleware multiple origins example
Example of allowing multiple specific origins:
app.use(
csrf({
origin: [
'https://myapp.example.com',
'https://development.myapp.example.com',
],
})
)
CSRF middleware secFetchSite specific value example
Example of allowing specific sec-fetch-site values:
app.use(csrf({ secFetchSite: 'same-origin' }))
app.use(csrf({ secFetchSite: ['same-origin', 'none'] }))
CSRF middleware origin option
The origin option specifies allowed origins for CSRF protection. It accepts three types: a string for a single allowed origin (e.g., 'https://example.com'), a string array for multiple allowed origins, or a function with signature (origin: string, context: Context) => boolean for custom validation. The default allows only the same origin as the request URL.
CSRF middleware dynamic secFetchSite validation example
Example of dynamic secFetchSite validation:
app.use(
csrf({
secFetchSite: (secFetchSite, c) => {
// Always allow same-origin
if (secFetchSite === 'same-origin') return true
// Allow cross-site for webhook endpoints
if (
secFetchSite === 'cross-site' &&
c.req.path.startsWith('/webhook/')
) {
return true
}
return false
},
})
)
This function validates secFetchSite values conditionally based on request properties like the path.
CSRF middleware dynamic origin validation example
Example of dynamic origin validation with regex:
app.use(
'*',
csrf({
origin: (origin) =>
/https:\/\/(\w+\.)?myapp\.example\.com$/.test(origin),
})
)
This uses a function to validate the origin against a regex pattern. It is strongly recommended that the protocol be verified to ensure a match to the end of the string ($), and never do a forward match.
CSRF middleware secFetchSite option
The secFetchSite option specifies allowed Sec-Fetch-Site header values for CSRF protection using Fetch Metadata. It accepts three types: a string for a single allowed value (e.g., 'same-origin'), a string array for multiple allowed values (e.g., ['same-origin', 'none']), or a function with signature (secFetchSite: string, context: Context) => boolean for custom validation. The default only allows 'same-origin'. Standard Sec-Fetch-Site values are: 'same-origin' (request from same origin), 'same-site' (request from same site with different subdomain), 'cross-site' (request from different site), and 'none' (request not from a web page such as browser address bar or bookmark).
CSRF middleware default usage
The default csrf() middleware with no options performs both origin and sec-fetch-site validation: app.use(csrf())
CSRF middleware browser compatibility limitation
Old browsers that do not send Origin headers, or environments that use reverse proxies to remove these headers, may not work well with the CSRF middleware. In such environments, use other CSRF token methods instead.
CSRF middleware validation logic
The CSRF middleware protects against CSRF attacks by checking both the Origin header and the Sec-Fetch-Site header. The request is allowed if either validation passes. The middleware only validates requests that use unsafe HTTP methods (not GET, HEAD, or OPTIONS) and have content types that can be sent by HTML forms (application/x-www-form-urlencoded, multipart/form-data, or text/plain).
CSRF middleware import
Import the CSRF middleware from 'hono/csrf' using: import { csrf } from 'hono/csrf'
ETag middleware retainedHeaders example usage
The retainedHeaders option can include custom headers along with default headers. Example: app.use('/etag/*', etag({ retainedHeaders: ['x-message', ...RETAINED_304_HEADERS] })). The RETAINED_304_HEADERS constant is imported from 'hono/etag'.
ETag middleware retainedHeaders option
The retainedHeaders option is a string array (optional) that specifies which headers to retain in 304 Not Modified responses. The default retained headers are Cache-Control, Content-Location, Date, ETag, Expires, and Vary. These defaults are available via the RETAINED_304_HEADERS constant that can be imported from 'hono/etag'.
ETag middleware weak validation option
The weak option is a boolean (optional, default false). When set to true, it uses weak validation and adds 'w/' prefix to the ETag value. Weak validation is defined at https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#weak_validation.
ETag middleware usage
The ETag middleware is applied using app.use() with a route pattern. For example: app.use('/etag/*', etag()). It generates ETag headers for responses matching the specified route.
ETag middleware import
The ETag middleware is imported from 'hono/etag'. Import statement: import { etag } from 'hono/etag'.
ETag middleware generateDigest option
The generateDigest option is a function with signature (body: Uint8Array) => ArrayBuffer | Promise<ArrayBuffer> (optional). It allows custom digest generation instead of the default SHA-1 algorithm. The function receives the response body as Uint8Array and returns a hash as ArrayBuffer or Promise<ArrayBuffer>.
ipRestriction with Deno example
For Deno, pass getConnInfo from 'hono/deno' as the first argument to ipRestriction.
ipRestriction custom error handling
To customize the error response, provide a third argument to ipRestriction that is an async function receiving (remote, c). This function should return a Response object. Example: async (remote, c) => c.text(`Blocking access from ${remote.addr}`, 403)
ipRestriction middleware signature and parameters
ipRestriction takes three parameters: a getConnInfo function appropriate for the runtime environment, a configuration object with denyList and allowList properties, and an optional error handler function. The configuration object has denyList (array of IP rules to deny) and allowList (array of IP rules to allow). The optional third parameter is an error handler that receives (remote, c) and should return a Response.
ipRestriction with Bun example
Example for Bun: 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'] })); app.get('/', (c) => c.text('Hello Hono!'));
IP restriction rules format for IPv6
IPv6 rules can be written in three formats: static IP address (e.g., '::1'), CIDR notation (e.g., '::1/10'), or wildcard for all addresses ('*').
ipRestriction middleware import
The ipRestriction middleware is imported from 'hono/ip-restriction'. It is used to limit access to resources based on IP address.
getConnInfo helper required for ipRestriction
The ipRestriction middleware requires a getConnInfo function appropriate for the runtime environment (Bun, Deno, etc.) to be passed as the first argument. The getConnInfo helper is imported from runtime-specific modules like 'hono/bun' or 'hono/deno'.
JWT alg option
The alg option (required, string) specifies the algorithm type used for verifying tokens. Available types are: HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA.
JWT cookie option
The cookie option (optional, string) retrieves the JWT token from a cookie header using the specified value as a key, then validates it as a token. When set, the Authorization header is not checked.
JWT secret option
The secret option (required, string) is the secret key value used for verifying JWT tokens.
JWT headerName option
The headerName option (optional, string) specifies the name of the header to look for the JWT token. The default is 'Authorization'. Example: headerName: 'x-custom-auth-header'
JWT realm option
The realm option (optional, string) specifies the protection space described by the realm parameter of the WWW-Authenticate challenge header returned on 401 responses. The default is the request URL. Example: realm: 'my-protected-api'
JWT payload access in handlers
Access the JWT payload in route handlers using c.get('jwtPayload'). This returns the decoded token claims as an object.
JWT Auth Middleware import and type
Import the jwt middleware and JwtVariables type from 'hono/jwt'. Use JwtVariables to type the app's Variables to enable type inference for c.get('jwtPayload').
JWT Auth Middleware basic usage
The jwt() middleware requires two options: secret (string) and alg (string algorithm type). It checks for an Authorization header by default if the cookie option is not set. Example: app.use('/auth/*', jwt({ secret: 'it-is-very-secret', alg: 'HS256' }))
JWT middleware with dynamic secret from environment
To use an environment variable for the secret (e.g., c.env.JWT_SECRET), wrap the jwt() middleware in a custom middleware function that creates the jwt middleware with the dynamic secret: app.use('/auth/*', (c, next) => { const jwtMiddleware = jwt({ secret: c.env.JWT_SECRET, alg: 'HS256' }); return jwtMiddleware(c, next); })
JWT Authorization header format requirement
The Authorization header sent from the client must include a specified scheme, such as 'Bearer my.token.value' or 'Basic my.token.value'.