Hono Web Framework

repository·main·Indexed 41 days ago

https://github.com/honojs/website

A small, fast, web standard-based web framework. Hono leverages standard Web APIs like Request, Response, and Fetch, providing a lightweight interface for building applications on runtimes such as Cloudflare Workers, Bun, Deno, and Node.js. Key features include a flexible Context object for request/response handling, built-in support for HTTPExceptions, and a variety of router presets optimized for different deployment environments.

Tokens
114.2K
Snippets
429
Records
477
Agent score
51%

What's inside Hono

  1. Overview of the Hono website repository

    main
    This repository contains the source code and assets for the official Hono website (hono.dev). The site is built using VitePress and is deployed to Cloudflare Workers. Note that the website itself does not use the Hono framework.
  2. Overview of Hono web framework

    main

    Hono is a small, simple, and ultrafast web framework built on Web Standards. It is designed to be lightweight and highly portable across various JavaScript runtimes.

    Key Features

    • Ultrafast & Lightweight: Uses the RegExpRouter for high performance. The hono/tiny preset is under 14kB.
    • Multi-runtime Support: The same code runs on Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Netlify, AWS Lambda, Lambda@Edge, and Node.js.
    • Batteries Included: Provides built-in middleware, support for custom and third-party middleware, and various helpers.
    • Delightful DX: Offers clean APIs and first-class TypeScript support.
  3. Supported runtimes for Hono

    main

    Hono can run on any runtime that supports Web Standards. Supported environments include:

    • Cloudflare Workers (workerd)
    • Deno
    • Bun
    • Fastly Compute
    • AWS Lambda
    • Node.js (via a Node.js adapter)
    • Vercel (edge-light)
    • WebAssembly (via [WebAssembly System Interface (WASI)][wasi] and [wasi:http][wasi-http])
    • Netlify and other platforms compatible with Web Standards.

    Because of this architecture, the same Hono code can be deployed across all these platforms without changes.

  4. Use the Route Helper for enhanced routing information

    main

    The Route Helper provides tools to access detailed information about matched routes and the current route being processed. This is particularly useful for debugging and developing middleware. You can import the following helpers from hono/route:

    • matchedRoutes(c): Returns an array of all matched routes.
    • routePath(c, [index]): Returns the route path pattern.
    • baseRoutePath(c, [index]): Returns the base path pattern.
    • basePath(c): Returns the base path with embedded parameters from the actual request.
    import { Hono } from 'hono'
    import {
      matchedRoutes,
      routePath,
      baseRoutePath,
      basePath,
    } from 'hono/route'
  5. Explore Third-party Middleware for Hono

    main
    Hono supports a wide ecosystem of third-party middleware that are not bundled with the core package. These middleware components typically leverage external libraries to provide specialized functionality such as authentication, validation, monitoring, and more. You can find these packages in the official Hono middleware repository or via individual community maintainers.
  6. What is a Hono Stack and RPC?

    main

    A Hono Stack is a combination of components used to build full-stack applications with end-to-end type safety. It typically consists of:

    • Hono: The API Server.
    • Zod: The validator for request data.
    • Zod Validator Middleware: @hono/zod-validator to bridge Zod and Hono.
    • hc (HTTP Client): The client that reads the API specification to provide type-safe endpoint access.

    This setup enables RPC (Remote Procedure Call), allowing the client to access endpoint types and request shapes automatically based on the server's implementation.

  7. What is middleware in Hono

    main
    In Hono, a 'Handler' is the primitive that returns a Response. 'Middleware' is a function that executes both before and after the Handler, intercepting the Request and Response. This follows an 'onion structure' where middleware wraps around the core handler, allowing you to perform actions before the request reaches the handler and after the response is generated.
  8. Enable Lambda Response Streaming

    main

    To use AWS Lambda's Response Streaming feature, you must set the invokeMode to RESPONSE_STREAM in your CDK configuration.

    In your Hono code, instead of using handle, you must use streamHandle from hono/aws-lambda to support traditional Hono streaming (e.g., using streamText).

    // CDK Configuration
    fn.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.NONE,
      invokeMode: lambda.InvokeMode.RESPONSE_STREAM,
    })
    
    // Hono Implementation
    import { Hono } from 'hono'
    import { streamHandle } from 'hono/aws-lambda'
    import { streamText } from 'hono/streaming'
    
    const app = new Hono()
    
    app.get('/stream', async (c) => {
      return streamText(c, async (stream) => {
        for (let i = 0; i < 3; i++) {
          await stream.writeln(`${i}`)
          await stream.sleep(1)
        }
      })
    })
    
    export const handler = streamHandle(app)
  9. Import Hono and middleware in Deno (npm vs JSR)

    main

    Hono is available via both npm and jsr. When using Deno, you must configure your deno.json imports correctly.

    Important for Middleware: To use Hono middleware, you must use the Deno directory syntax for the Hono import (e.g., hono/ mapping to npm:/hono/).

    Consistency Rule: For proper TypeScript type inference, ensure that Hono and any third-party middleware you use come from the same registry (either both from npm or both from jsr).

    Example using npm:

    {
      "imports": {
        "hono": "npm:hono",
        "zod": "npm:zod",
        "@hono/zod-validator": "npm:@hono/zod-validator",
        "hono/": "npm:/hono/"
      }
    }

    Example using JSR:

    {
      "imports": {
        "hono": "jsr:@hono/hono",
        "zod": "npm:zod",
        "@hono/zod-validator": "jsr:@hono/zod-validator"
      }
    }
  10. Use Combine Middleware to group middleware functions

    main

    Combine Middleware allows you to group multiple middleware functions into a single middleware unit using logical operators. This is useful for implementing complex access control, conditional rate limiting, or environment-specific rules.

    To use Combine Middleware, import the desired logic function from hono/combine:

    import { some, every, except } from 'hono/combine'
    import { Hono } from 'hono'
    import { some, every, except } from 'hono/combine'
    
    const app = new Hono()
    
    // Example of complex access control
    app.use(
      '*',
      some(
        every(
          ipRestriction(getConnInfo, { allowList: ['192.168.0.2'] }),
          bearerAuth({ token })
        ),
        rateLimit()
      )
    )
  11. Implement dynamic CORS logic with callbacks

    main

    You can pass callback functions to the origin and allowMethods options to determine allowed values dynamically based on the incoming request's origin or the Hono Context.

    This is useful for allowing multiple subdomains or restricting specific methods to specific origins.

    // Dynamic origin based on subdomain
    app.use(
      '/api4/*',
      cors({
        origin: (origin, c) => {
          return origin.endsWith('.example.com')
            ? origin
            : 'http://example.com'
        },
      })
    )
    
    // Dynamic methods based on origin
    app.use(
      '/api5/*',
      cors({
        origin: (origin) =>
          origin === 'https://example.com' ? origin : '*',
        allowMethods: (origin, c) =>
          origin === 'https://example.com'
            ? ['GET', 'HEAD', 'POST', 'PATCH', 'DELETE']
            : ['GET', 'HEAD'],
      })
    )
  12. Use the Factory Helper to manage TypeScript types

    main

    The Factory Helper simplifies creating Hono components like Middleware and Apps while ensuring consistent TypeScript types for Env (Bindings and Variables). Instead of manually passing Env types to every middleware and application instance, you define them once in a factory.

    import { createFactory } from 'hono/factory'
    
    type Env = {
      Variables: { foo: string }
    }
    
    const factory = createFactory<Env>()
    
    // All components created from this factory inherit the Env type
    const app = factory.createApp()
    const middleware = factory.createMiddleware(async (c, next) => {
      const value = c.var.foo // Properly typed
      await next()
    })