1. Project Overview & Quickstart (honojs/LICENSE)
LICENSE
Open-source repository honojs/LICENSE
Repository Details
- Repository: honojs/LICENSE
- Primary Language: Code
Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.
2. Official Technical Reference & Guides (honojs/website)
File: README.md
Repository for hono.dev
This is a repository for the Hono website "hono.dev".
Features
- Built with VitePress
- Deploy to Cloudflare Workers
- Not using Hono :)
Contribution
Contribution welcome!
You can help us by adding explanations, correcting grammar, or fixing a typo.
License
MIT
Author
Yusuke Wada https://github.com/yusukebe
File: docs/helpers/accepts.md
Accepts Helper
Accepts Helper helps to handle Accept headers in the Requests.
Import
import { Hono } from 'hono'
import { accepts } from 'hono/accepts'`accepts()`
The accepts() function looks at the Accept header, such as Accept-Encoding and Accept-Language, and returns the proper value.
import { accepts } from 'hono/accepts'
app.get('/', (c) => {
const accept = accepts(c, {
header: 'Accept-Language',
supports: ['en', 'ja', 'zh'],
default: 'en',
})
return c.json({ lang: accept })
})`AcceptHeader` type
The definition of the AcceptHeader type is as follows.
export type AcceptHeader =
| 'Accept'
| 'Accept-Charset'
| 'Accept-Encoding'
| 'Accept-Language'
| 'Accept-Patch'
| 'Accept-Post'
| 'Accept-Ranges'Options
header: `AcceptHeader`
The target accept header.
supports: `string[]`
The header values which your application supports.
default: `string`
The default values.
match: `(accepts: Accept[], config: acceptsConfig) => string`
The custom match function.
File: docs/helpers/adapter.md
Adapter Helper
The Adapter Helper provides a seamless way to interact with various platforms through a unified interface.
Import
import { Hono } from 'hono'
import { env, getRuntimeKey } from 'hono/adapter'`env()`
The env() function facilitates retrieving environment variables across different runtimes, extending beyond just Cloudflare Workers' Bindings. The value that can be retrieved with env(c) may be different for each runtime.
import { env } from 'hono/adapter'
app.get('/env', (c) => {
// NAME is process.env.NAME on Node.js or Bun
// NAME is the value written in `wrangler.toml` on Cloudflare
const { NAME } = env<{ NAME: string }>(c)
return c.text(NAME)
})Supported Runtimes, Serverless Platforms and Cloud Services:
- Cloudflare Workers
wrangler.tomlwrangler.jsonc
- Deno
Deno.env.envfile
- Bun
Bun.envprocess.env
- Node.js
process.env
- Vercel
- AWS Lambda
- Lambda@Edge
Environment Variables on Lambda are not supported by Lambda@Edge, you need to use Lambda@Edge event as an alternative. - Fastly Compute
On Fastly Compute, you can use the ConfigStore to manage user-defined data. - Netlify
On Netlify, you can use the Netlify Contexts to manage user-defined data.
Specify the runtime
You can specify the runtime to get environment variables by passing the runtime key as the second argument.
app.get('/env', (c) => {
const { NAME } = env<{ NAME: string }>(c, 'workerd')
return c.text(NAME)
})`getRuntimeKey()`
The getRuntimeKey() function returns the identifier of the current runtime.
app.get('/', (c) => {
if (getRuntimeKey() === 'workerd') {
return c.text('You are on Cloudflare')
} else if (getRuntimeKey() === 'bun') {
return c.text('You are on Bun')
}
...
})Available Runtimes Keys
Here are the available runtimes keys, unavailable runtime key runtimes may be supported and labeled as other, with some being inspired by WinterCG's Runtime Keys:
workerd- Cloudflare Workersdenobunnodeedge-light- Vercel Edge Functionsfastly- Fastly Computeother- Other unknown runtimes keys
File: docs/helpers/conninfo.md
ConnInfo Helper
The ConnInfo Helper helps you to get the connection information. For example, you can get the client's remote address easily.
Import
::: code-group
import { Hono } from 'hono'
import { getConnInfo } from 'hono/cloudflare-workers'import { Hono } from 'hono'
import { getConnInfo } from 'hono/deno'import { Hono } from 'hono'
import { getConnInfo } from 'hono/bun'import { Hono } from 'hono'
import { getConnInfo } from 'hono/vercel'import { Hono } from 'hono'
import { getConnInfo } from 'hono/aws-lambda'import { Hono } from 'hono'
import { getConnInfo } from 'hono/netlify'import { Hono } from 'hono'
import { getConnInfo } from 'hono/lambda-edge'import { Hono } from 'hono'
import { getConnInfo } from '@hono/node-server/conninfo':::
Usage
const app = new Hono()
app.get('/', (c) => {
const info = getConnInfo(c) // info is `ConnInfo`
return c.text(`Your remote address is ${info.remote.address}`)
})Type Definitions
The type definitions of the values that you can get from getConnInfo() are the following:
type AddressType = 'IPv6' | 'IPv4' | undefined
type NetAddrInfo = {
/**
* Transport protocol type
*/
transport?: 'tcp' | 'udp'
/**
* Transport port number
*/
port?: number
address?: string
addressType?: AddressType
} & (
| {
/**
* Host name such as IP Addr
*/
address: string
/**
* Host name type
*/
addressType: AddressType
}
| {}
)
/**
* HTTP Connection information
*/
interface ConnInfo {
/**
* Remote information
*/
remote: NetAddrInfo
}File: docs/helpers/cookie.md
Cookie Helper
The Cookie Helper provides an easy interface to manage cookies, enabling developers to set, parse, and delete cookies seamlessly.
Import
import { Hono } from 'hono'
import {
deleteCookie,
getCookie,
getSignedCookie,
setCookie,
setSignedCookie,
generateCookie,
generateSignedCookie,
} from 'hono/cookie'Usage
Regular cookies
app.get('/cookie', (c) => {
setCookie(c, 'cookie_name', 'cookie_value')
const yummyCookie = getCookie(c, 'cookie_name')
deleteCookie(c, 'cookie_name')
const allCookies = getCookie(c)
// ...
})Signed cookies
NOTE: Setting and retrieving signed cookies returns a Promise due to the async nature of the WebCrypto API, which is used to create HMAC SHA-256 signatures.
app.get('/signed-cookie', (c) => {
const secret = 'secret' // make sure it's a large enough string to be secure
await setSignedCookie(c, 'cookie_name0', 'cookie_value', secret)
const fortuneCookie = await getSignedCookie(
c,
secret,
'cookie_name0'
)
deleteCookie(c, 'cookie_name0')
// `getSignedCookie` will return `false` for a specified cookie if its signature fails verification
const allSignedCookies = await getSignedCookie(c, secret)
// ...
})[!NOTE]
getSignedCookiedistinguishes two cases. A cookie that has a signature but fails verification returnsfalse. A cookie that does not have a valid signature format is treated as not being a signed cookie at all and returnsundefinedโ the same as when the cookie is not present. This rule applies both when retrieving a single cookie by name and when retrieving all signed cookies. Since bothfalseandundefinedare falsy,if (!value)handles both cases.
Cookie Generation
generateCookie and generateSignedCookie functions allow you to create cookie strings directly without setting them in the response headers.
`generateCookie`
// Basic cookie generation
const cookie = generateCookie('delicious_cookie', 'macha')
// Returns: 'delicious_cookie=macha; Path=/'
// Cookie with options
const cookie = generateCookie('delicious_cookie', 'macha', {
path: '/',
secure: true,
httpOnly: true,
domain: 'example.com',
})`generateSignedCookie`
// Basic signed cookie generation
const signedCookie = await generateSignedCookie(
'delicious_cookie',
'macha',
'secret chocolate chips'
)
// Signed cookie with options
const signedCookie = await generateSignedCookie(
'delicious_cookie',
'macha',
'secret chocolate chips',
{
path: '/',
secure: true,
httpOnly: true,
}
)Note: Unlike setCookie and setSignedCookie, these functions only generate the cookie strings. You need to manually set them in headers if needed.
Options
`setCookie` & `setSignedCookie`
- domain:
string - expires:
Date - httpOnly:
boolean - maxAge:
number - path:
string - secure:
boolean - sameSite:
'Strict'|'Lax'|'None' - priority:
'Low' | 'Medium' | 'High' - prefix:
secure|'host' - partitioned:
boolean
Example:
// Regular cookies
setCookie(c, 'great_cookie', 'banana', {
path: '/',
secure: true,
domain: 'example.com',
httpOnly: true,
maxAge: 1000,
expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
sameSite: 'Strict',
})
// Signed cookies
await setSignedCookie(
c,
'fortune_cookie',
'lots-of-money',
'secret ingredient',
{
path: '/',
secure: true,
domain: 'example.com',
httpOnly: true,
maxAge: 1000,
expires: new Date(Date.UTC(2000, 11, 24, 10, 30, 59, 900)),
sameSite: 'Strict',
}
)`deleteCookie`
- path:
string - secure:
boolean - domain:
string
Example:
deleteCookie(c, 'banana', {
path: '/',
secure: true,
domain: 'example.com',
})deleteCookie returns the deleted value:
const deletedCookie = deleteCookie(c, 'delicious_cookie')`__Secure-` and `__Host-` prefix
The Cookie helper supports __Secure- and __Host- prefixes for cookie names.
If you want to verify if the cookie name has a prefix, specify the prefix option.
const securePrefixCookie = getCookie(c, 'yummy_cookie', 'secure')
const hostPrefixCookie = getCookie(c, 'yummy_cookie', 'host')
const securePrefixSignedCookie = await getSignedCookie(
c,
secret,
'fortune_cookie',
'secure'
)
const hostPrefixSignedCookie = await getSignedCookie(
c,
secret,
'fortune_cookie',
'host'
)Also, if you wish to specify a prefix when setting the cookie, specify a value for the prefix option.
setCookie(c, 'delicious_cookie', 'macha', {
prefix: 'secure', // or `host`
})
await setSignedCookie(
c,
'delicious_cookie',
'macha',
'secret choco chips',
{
prefix: 'secure', // or `host`
}
)Following the best practices
A New Cookie RFC (a.k.a cookie-bis) and CHIPS include some best practices for Cookie settings that developers should follow.
- RFC6265bis-13
Max-Age/Expireslimitation__Host-/__Secure-prefix limitation
- CHIPS-01
Partitionedlimitation
Hono is following the best practices.
The cookie helper will throw an Error when parsing cookies under the following conditions:
- The cookie name starts with
__Secure-, butsecureoption is not set. - The cookie name starts with
__Host-, butsecureoption is not set. - The cookie name starts with
__Host-, butpathis not/. - The cookie name starts with
__Host-, butdomainis set. - The
maxAgeoption value is greater than 400 days. - The
expiresoption value is 400 days later than the current time.
File: docs/helpers/dev.md
Dev Helper
Dev Helper provides useful methods you can use in development.
import { Hono } from 'hono'
import { getRouterName, showRoutes } from 'hono/dev'`getRouterName()`
You can get the name of the currently used router with getRouterName().
const app = new Hono()
// ...
console.log(getRouterName(app))`showRoutes()`
showRoutes() function displays the registered routes in your console.
Consider an application like the following:
const app = new Hono().basePath('/v1')
app.get('/posts', (c) => {
// ...
})
app.get('/posts/:id', (c) => {
// ...
})
app.post('/posts', (c) => {
// ...
})
showRoutes(app, {
verbose: true,
})When this application starts running, the routes will be shown in your console as follows:
GET /v1/posts
GET /v1/posts/:id
POST /v1/postsOptions
verbose: `boolean`
When set to true, it displays verbose information.
colorize: `boolean`
When set to false, the output will not be colored.
File: docs/helpers/factory.md
Factory Helper
The Factory Helper provides useful functions for creating Hono's components such as Middleware. Sometimes it's difficult to set the proper TypeScript types, but this helper facilitates that.
Import
import { Hono } from 'hono'
import { createFactory, createMiddleware } from 'hono/factory'`createFactory()`
createFactory() will create an instance of the Factory class.
import { createFactory } from 'hono/factory'
const factory = createFactory()You can pass your Env types as Generics:
type Env = {
Variables: {
foo: string
}
}
const factory = createFactory<Env>()Options
defaultAppOptions: `HonoOptions`
The default options to pass to the Hono application created by createApp().
const factory = createFactory({
defaultAppOptions: { strict: false },
})
const app = factory.createApp() // `strict: false` is applied`createMiddleware()`
createMiddleware() is shortcut of factory.createMiddleware().
This function will create your custom middleware.
const messageMiddleware = createMiddleware(async (c, next) => {
await next()
c.res.headers.set('X-Message', 'Good morning!')
})Tip: If you want to get an argument like message, you can create it as a function like the following.
const messageMiddleware = (message: string) => {
return createMiddleware(async (c, next) => {
await next()
c.res.headers.set('X-Message', message)
})
}
app.use(messageMiddleware('Good evening!'))`factory.createHandlers()`
createHandlers() helps to define handlers in a different place than app.get('/').
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'
// ...
const factory = createFactory()
const middleware = factory.createMiddleware(async (c, next) => {
c.set('foo', 'bar')
await next()
})
const handlers = factory.createHandlers(logger(), middleware, (c) => {
return c.json(c.var.foo)
})
app.get('/api', ...handlers)`factory.createApp()`
createApp() helps to create an instance of Hono with the proper types. If you use this method with createFactory(), you can avoid redundancy in the definition of the Env type.
If your application is like this, you have to set the Env in two places:
import { createMiddleware } from 'hono/factory'
type Env = {
Variables: {
myVar: string
}
}
// 1. Set the `Env` to `new Hono()`
const app = new Hono<Env>()
// 2. Set the `Env` to `createMiddleware()`
const mw = createMiddleware<Env>(async (c, next) => {
await next()
})
app.use(mw)By using createFactory() and createApp(), you can set the Env only in one place.
import { createFactory } from 'hono/factory'
// ...
// Set the `Env` to `createFactory()`
const factory = createFactory<Env>()
const app = factory.createApp()
// factory also has `createMiddleware()`
const mw = factory.createMiddleware(async (c, next) => {
await next()
})createFactory() can receive the initApp option to initialize an app created by createApp(). The following is an example that uses the option.
// factory-with-db.ts
type Env = {
Bindings: {
MY_DB: D1Database
}
Variables: {
db: DrizzleD1Database
}
}
export default createFactory<Env>({
initApp: (app) => {
app.use(async (c, next) => {
const db = drizzle(c.env.MY_DB)
c.set('db', db)
await next()
})
},
})// crud.ts
import factoryWithDB from './factory-with-db'
const app = factoryWithDB.createApp()
app.post('/posts', (c) => {
c.var.db.insert()
// ...
})File: docs/helpers/jwt.md
JWT Authentication Helper
This helper provides functions for encoding, decoding, signing, and verifying JSON Web Tokens (JWTs). JWTs are commonly used for authentication and authorization purposes in web applications. This helper offers robust JWT functionality with support for various cryptographic algorithms.
Import
To use this helper, you can import it as follows:
import { decode, sign, verify } from 'hono/jwt'::: info
JWT Middleware also import the jwt function from the hono/jwt.
:::
`sign()`
This function generates a JWT token by encoding a payload and signing it using the specified algorithm and secret.
sign(
payload: unknown,
secret: string,
alg?: 'HS256';
): Promise<string>;Example
import { sign } from 'hono/jwt'
const payload = {
sub: 'user123',
role: 'admin',
exp: Math.floor(Date.now() / 1000) + 60 * 5, // Token expires in 5 minutes
}
const secret = 'mySecretKey'
const token = await sign(payload, secret)Options
payload: `unknown`
The JWT payload to be signed. You can include other claims like in Payload Validation.
secret: `string`
The secret key used for JWT verification or signing.
alg: [AlgorithmTypes](#supported-algorithmtypes)
The algorithm used for JWT signing or verification. The default is HS256.
`verify()`
This function checks if a JWT token is genuine and still valid. It ensures the token hasn't been altered and checks validity only if you added Payload Validation.
verify(
token: string,
secret: string,
alg: 'HS256';
issuer?: string | RegExp;
aud?: string | string[] | RegExp;
): Promise<any>;Example
import { verify } from 'hono/jwt'
const tokenToVerify = 'token'
const secretKey = 'mySecretKey'
const decodedPayload = await verify(tokenToVerify, secretKey, 'HS256')
console.log(decodedPayload)Options
token: `string`
The JWT token to be verified.
secret: `string`
The secret key used for JWT verification or signing.
alg: [AlgorithmTypes](#supported-algorithmtypes)
The algorithm used for JWT signing or verification.
issuer: `string | RegExp`
The expected issuer used for JWT verification.
aud: `string | string[] | RegExp`
The expected audience used for JWT verification. If this is set, the token must include an aud claim and at least one audience value must match.
`decode()`
This function decodes a JWT token without performing signature verification. It extracts and returns the header and payload from the token.
decode(token: string): { header: any; payload: any };Example
import { decode } from 'hono/jwt'
// Decode the JWT token
const tokenToDecode =
'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAidXNlcjEyMyIsICJyb2xlIjogImFkbWluIn0.JxUwx6Ua1B0D1B0FtCrj72ok5cm1Pkmr_hL82sd7ELA'
const { header, payload } = decode(tokenToDecode)
console.log('Decoded Header:', header)
console.log('Decoded Payload:', payload)Options
token: `string`
The JWT token to be decoded.
The
decodefunction allows you to inspect the header and payload of a JWT token without performing verification. This can be useful for debugging or extracting information from JWT tokens.
Payload Validation
When verifying a JWT token, the following payload validations are performed:
exp: The token is checked to ensure it has not expired.nbf: The token is checked to ensure it is not being used before a specified time.iat: The token is checked to ensure it is not issued in the future.iss: The token is checked to ensure it has been issued by a trusted issuer.aud: The token is checked to ensure it is intended for an accepted audience when theaudverification parameter is set.
Please ensure that your JWT payload includes these fields, as an object, if you intend to perform these checks during verification.
Custom Error Types
The module also defines custom error types to handle JWT-related errors.
JwtAlgorithmNotImplemented: Indicates that the requested JWT algorithm is not implemented.JwtTokenInvalid: Indicates that the JWT token is invalid.JwtTokenNotBefore: Indicates that the token is being used before its valid date.JwtTokenExpired: Indicates that the token has expired.JwtTokenIssuedAt: Indicates that the "iat" claim in the token is incorrect.JwtTokenIssuer: Indicates that the "iss" claim in the token is incorrect.JwtPayloadRequiresAud: Indicates that anaudclaim is required whenaudverification is configured.JwtTokenAudience: Indicates that the token'saudclaim does not match the expected audience.JwtTokenSignatureMismatched: Indicates a signature mismatch in the token.
Supported AlgorithmTypes
The module supports the following JWT cryptographic algorithms:
HS256: HMAC using SHA-256HS384: HMAC using SHA-384HS512: HMAC using SHA-512RS256: RSASSA-PKCS1-v1_5 using SHA-256RS384: RSASSA-PKCS1-v1_5 using SHA-384RS512: RSASSA-PKCS1-v1_5 using SHA-512PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256PS384: RSASSA-PSS using SHA-386 and MGF1 with SHA-386PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512ES256: ECDSA using P-256 and SHA-256ES384: ECDSA using P-384 and SHA-384ES512: ECDSA using P-521 and SHA-512EdDSA: EdDSA using Ed25519