hono Documentation

Web framework built on Web Standards

31,652 stars TypeScript TypeScript 1 file Β· ~7,915 tokens #aws-lambda#bun#cloudflare#cloudflare-workers#deno#npm#router#typescript
RAW Doc

Technical Documentation: honojs/hono

ℹ️ Provenance: Hybrid Fusion: honojs/hono + honojs/website Β· CodeWiki Reference Β· Recency: Active (< 180 days)

1. Project Overview & Quickstart (honojs/hono)












Hono - means flameπŸ”₯ in Japanese - is a small, simple, and ultrafast web framework built on Web Standards. It works on any JavaScript runtime: Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, AWS Lambda, Lambda@Edge, and Node.js.

Fast, but not only fast.

ts
import { Hono } from 'hono'
const app = new Hono()

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

export default app

Quick Start

bash
npm create hono@latest

Features

  • Ultrafast πŸš€ - The router RegExpRouter is really fast. Not using linear loops. Fast.
  • Lightweight πŸͺΆ - The hono/tiny preset is under 12kB. Hono has zero dependencies and uses only the Web Standard API.
  • Multi-runtime 🌍 - Works on Cloudflare Workers, Fastly Compute, Deno, Bun, AWS Lambda, Lambda@Edge, or Node.js. The same code runs on all platforms.
  • Batteries Included πŸ”‹ - Hono has built-in middleware, custom middleware, and third-party middleware. Batteries included.
  • Delightful DX πŸ˜ƒ - Super clean APIs. First-class TypeScript support. Now, we've got "Types".

Documentation

The documentation is available on hono.dev.

Migration

The migration guide is available on docs/MIGRATION.md.

Communication

X and Discord channel are available.

Contributing

Contributions Welcome! You can contribute in the following ways.

  • Create an Issue - Propose a new feature. Report a bug.
  • Build middleware and libraries - Grow the Hono ecosystem.
  • Share - Share your thoughts on the Blog, X, and others.
  • Sponsor - Support the maintainers through GitHub Sponsors: @yusukebe and @usualoma.
  • Make your application - Please try to use Hono.

For more details, see docs/CONTRIBUTING.md.

Contributors

Thanks to all contributors!

Authors

Yusuke Wada https://github.com/yusukebe

RegExpRouter, SmartRouter, LinearRouter, and PatternRouter are created by Taku Amano https://github.com/usualoma

License

Distributed under the MIT License. See LICENSE for more information.

2. Official Technical Reference & Guides (honojs/website)

File: docs/helpers/accepts.md

Accepts Helper

Accepts Helper helps to handle Accept headers in the Requests.

Import

ts
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.

ts
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.

ts
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

ts
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.

ts
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:

Specify the runtime

You can specify the runtime to get environment variables by passing the runtime key as the second argument.

ts
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.

ts
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 Workers
  • deno
  • bun
  • node
  • edge-light - Vercel Edge Functions
  • fastly - Fastly Compute
  • other - 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

The adapter for each runtime is a separate package (@hono/cloudflare-workers, @hono/deno, @hono/bun, ...). Install the one for your runtime.

::: code-group

ts [cloudflare workers]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/cloudflare-workers'
ts [deno]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/deno'
ts [bun]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/bun'
ts [vercel]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/vercel'
ts [aws lambda]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/aws-lambda'
ts [netlify]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/netlify'
ts [lambda@edge]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/lambda-edge'
ts [node.js]
import { Hono } from 'hono'
import { getConnInfo } from '@hono/node-server/conninfo'

:::

Usage

ts
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:

ts
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
}

The Cookie Helper provides an easy interface to manage cookies, enabling developers to set, parse, and delete cookies seamlessly.

Import

ts
import { Hono } from 'hono'
import {
  deleteCookie,
  getCookie,
  getSignedCookie,
  setCookie,
  setSignedCookie,
  generateCookie,
  generateSignedCookie,
} from 'hono/cookie'

Usage

Regular cookies

ts
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.

ts
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]
getSignedCookie distinguishes two cases. A cookie that has a signature but fails verification returns false. A cookie that does not have a valid signature format is treated as not being a signed cookie at all and returns undefined β€” 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 both false and undefined are falsy, if (!value) handles both cases.

generateCookie and generateSignedCookie functions allow you to create cookie strings directly without setting them in the response headers.

`generateCookie`

ts
// 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`

ts
// 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:

ts
// 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:

ts
deleteCookie(c, 'banana', {
  path: '/',
  secure: true,
  domain: 'example.com',
})

deleteCookie returns the deleted value:

ts
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.

ts
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.

ts
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/Expires limitation
    • __Host-/__Secure- prefix limitation
  • CHIPS-01
    • Partitioned limitation

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-, but secure option is not set.
  • The cookie name starts with __Host-, but secure option is not set.
  • The cookie name starts with __Host-, but path is not /.
  • The cookie name starts with __Host-, but domain is set.
  • The maxAge option value is greater than 400 days.
  • The expires option 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.

ts
import { Hono } from 'hono'
import { getRouterName, showRoutes } from 'hono/dev'

`getRouterName()`

You can get the name of the currently used router with getRouterName().

ts
const app = new Hono()

// ...

console.log(getRouterName(app))

`showRoutes()`

showRoutes() function displays the registered routes in your console.

Consider an application like the following:

ts
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:

txt
GET   /v1/posts
GET   /v1/posts/:id
POST  /v1/posts

Options

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

ts
import { Hono } from 'hono'
import { createFactory, createMiddleware } from 'hono/factory'

`createFactory()`

createFactory() will create an instance of the Factory class.

ts
import { createFactory } from 'hono/factory'

const factory = createFactory()

You can pass your Env types as Generics:

ts
type Env = {
  Variables: {
    foo: string
  }
}

const factory = createFactory<Env>()

Options

defaultAppOptions: `HonoOptions`

The default options to pass to the Hono application created by createApp().

ts
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.

ts
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.

ts
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('/').

ts
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:

ts
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.

ts
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.

ts
// 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()
    })
  },
})
ts
// 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:

ts
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.

ts
sign(
  payload: unknown,
  secret: string,
  alg?: 'HS256';

): Promise<string>;

Example

ts
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.

ts
verify(
  token: string,
  secret: string,
  alg: 'HS256';
  issuer?: string | RegExp;
  aud?: string | string[] | RegExp;
): Promise<any>;

Example

ts
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.

ts
decode(token: string): { header: any; payload: any };

Example

ts
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 decode function 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 the aud verification 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 an aud claim is required when aud verification is configured.
  • JwtTokenAudience: Indicates that the token's aud claim 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-256
  • HS384: HMAC using SHA-384
  • HS512: HMAC using SHA-512
  • RS256: RSASSA-PKCS1-v1_5 using SHA-256
  • RS384: RSASSA-PKCS1-v1_5 using SHA-384
  • RS512: RSASSA-PKCS1-v1_5 using SHA-512
  • PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
  • PS384: RSASSA-PSS using SHA-386 and MGF1 with SHA-386
  • PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512
  • ES256: ECDSA using P-256 and SHA-256
  • ES384: ECDSA using P-384 and SHA-384
  • ES512: ECDSA using P-521 and SHA-512
  • EdDSA: EdDSA using Ed25519

File: docs/helpers/proxy.md

Proxy Helper

Proxy Helper provides useful functions when using Hono application as a (reverse) proxy.

Import

ts
import { Hono } from 'hono'
import { proxy } from 'hono/proxy'

`proxy()`

proxy() is a fetch() API wrapper for proxy. The parameters and return value are the same as for fetch() (except for the proxy-specific options).

The Accept-Encoding header is replaced with an encoding that the current runtime can handle. Unnecessary response headers are removed, and a Response object is returned that can be sent from the handler.

Examples

Simple usage:

ts
app.get('/proxy/:path', (c) => {
  return proxy(`http://${originServer}/${c.req.param('path')}`)
})

Complicated usage:

ts
app.get('/proxy/:path', async (c) => {
  const res = await proxy(
    `http://${originServer}/${c.req.param('path')}`,
    {
      headers: {
        ...c.req.header(), // optional, specify only when forwarding all the request data (including credentials) is necessary.
        'X-Forwarded-For': '127.0.0.1',
        'X-Forwarded-Host': c.req.header('host'),
        Authorization: undefined, // do not propagate request headers contained in c.req.header('Authorization')
      },
    }
  )
  res.headers.delete('Set-Cookie')
  return res
})

Or you can pass the c.req as a parameter.

ts
app.all('/proxy/:path', (c) => {
  return proxy(`http://${originServer}/${c.req.param('path')}`, {
    ...c.req, // optional, specify only when forwarding all the request data (including credentials) is necessary.
    headers: {
      ...c.req.header(),
      'X-Forwarded-For': '127.0.0.1',
      'X-Forwarded-Host': c.req.header('host'),
      Authorization: undefined, // do not propagate request headers contained in c.req.header('Authorization')
    },
  })
})

You can override the default global fetch function with the customFetch option:

ts
app.get('/proxy', (c) => {
  return proxy('https://example.com/', {
    customFetch,
  })
})

Connection Header Processing

By default, proxy() ignores the Connection header to prevent Hop-by-Hop Header Injection attacks. You can enable strict RFC 9110 compliance with the strictConnectionProcessing option:

ts
// Default behavior (recommended for untrusted clients)
app.get('/proxy/:path', (c) => {
  return proxy(`http://${originServer}/${c.req.param('path')}`, c.req)
})

// Strict RFC 9110 compliance (use only in trusted environments)
app.get('/internal-proxy/:path', (c) => {
  return proxy(`http://${internalServer}/${c.req.param('path')}`, {
    ...c.req,
    strictConnectionProcessing: true,
  })
})

`ProxyFetch`

The type of proxy() is defined as ProxyFetch and is as follows

ts
interface ProxyRequestInit extends Omit<RequestInit, 'headers'> {
  raw?: Request
  customFetch?: (request: Request) => Promise<Response>
  strictConnectionProcessing?: boolean
  headers?:
    | HeadersInit
    | [string, string][]
    | Record<RequestHeader, string | undefined>
    | Record<string, string | undefined>
}

interface ProxyFetch {
  (
    input: string | URL | Request,
    init?: ProxyRequestInit
  ): Promise<Response>
}

File: docs/helpers/route.md

Route Helper

The Route Helper provides enhanced routing information for debugging and middleware development. It allows you to access detailed information about matched routes and the current route being processed.

Import

ts
import { Hono } from 'hono'
import {
  matchedRoutes,
  routePath,
  baseRoutePath,
  basePath,
} from 'hono/route'

Usage

Basic route information

ts
const app = new Hono()

app.get('/posts/:id', (c) => {
  const currentPath = routePath(c) // '/posts/:id'
  const routes = matchedRoutes(c) // Array of matched routes

  return c.json({
    path: currentPath,
    totalRoutes: routes.length,
  })
})

Working with sub-applications

ts
const app = new Hono()
const apiApp = new Hono()

apiApp.get('/posts/:id', (c) => {
  return c.json({
    routePath: routePath(c), // '/posts/:id'
    baseRoutePath: baseRoutePath(c), // '/api'
    basePath: basePath(c), // '/api' (with actual params)
  })
})

app.route('/api', apiApp)

`matchedRoutes()`

Returns an array of all routes that matched the current request, including middleware.

ts
app.all('/api/*', (c, next) => {
  console.log('API middleware')
  return next()
})

app.get('/api/users/:id', (c) => {
  const routes = matchedRoutes(c)
  // Returns: [
  //   { method: 'ALL', path: '/api/*', handler: [Function] },
  //   { method: 'GET', path: '/api/users/:id', handler: [Function] }
  // ]
  return c.json({ routes: routes.length })
})

`routePath()`

Returns the route path pattern registered for the current handler.

ts
app.get('/posts/:id', (c) => {
  console.log(routePath(c)) // '/posts/:id'
  return c.text('Post details')
})

Using with index parameter

You can optionally pass an index parameter to get the route path at a specific position, similar to Array.prototype.at().

ts
app.all('/api/*', (c, next) => {
  return next()
})

app.get('/api/users/:id', (c) => {
  console.log(routePath(c, 0)) // '/api/*' (first matched route)
  console.log(routePath(c, -1)) // '/api/users/:id' (last matched route)
  return c.text('User details')
})

`baseRoutePath()`

Returns the base path pattern of the current route as specified in routing.

ts
const subApp = new Hono()
subApp.get('/posts/:id', (c) => {
  return c.text(baseRoutePath(c)) // '/:sub'
})

app.route('/:sub', subApp)

Using with index parameter

You can optionally pass an index parameter to get the base route path at a specific
position, similar to Array.prototype.at().

ts
app.all('/api/*', (c, next) => {
  return next()
})

const subApp = new Hono()
subApp.get('/users/:id', (c) => {
  console.log(baseRoutePath(c, 0)) // '/' (first matched route)
  console.log(baseRoutePath(c, -1)) // '/api' (last matched route)
  return c.text('User details')
})

app.route('/api', subApp)

`basePath()`

Returns the base path with embedded parameters from the actual request.

ts
const subApp = new Hono()
subApp.get('/posts/:id', (c) => {
  return c.text(basePath(c)) // '/api' (for request to '/api/posts/123')
})

app.route('/:sub', subApp)

--- METRICS ---