Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/go-chi/chi/llms.txt

Use this file to discover all available pages before exploring further.

chi is deliberately small — the core router is under 1,000 lines of code with zero external dependencies. Functionality beyond routing is provided by a growing collection of first-party packages under the go-chi GitHub organization, each designed as a standard net/http middleware so it works with chi and any other compatible router.

Official packages

cors

Cross-origin resource sharing (CORS) middleware. Handles preflight requests and injects the appropriate Access-Control-* response headers.

docgen

Introspects a chi.Router at runtime and generates routing documentation in JSON or Markdown — no annotations required.

jwtauth

JWT authentication middleware. Verifies tokens on incoming requests and places the parsed claims on the request context.

hostrouter

Domain and host-based request routing. Mount separate chi routers for different hostnames or subdomains on a single listener.

httplog

Small but powerful structured HTTP request logging built on slog / zerolog. Captures status codes, latency, and request metadata.

httprate

HTTP request rate limiter. Supports per-IP, per-user, and global limits with configurable window sizes and custom key functions.

httptracer

HTTP request performance tracing library. Hooks into handler execution to record timing and trace data for observability pipelines.

httpvcr

Record and replay HTTP interactions with external services. Write deterministic tests for code that calls third-party APIs.

stampede

HTTP request coalescer. Collapses concurrent identical requests into a single upstream call and fans the response out to all waiting clients.

Using cors middleware

The cors package is one of the most commonly used chi ecosystem packages. Install it and attach it to your router’s middleware stack:
go get github.com/go-chi/cors
1
Import and configure
2
package main

import (
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/cors"
)

func main() {
	r := chi.NewRouter()

	r.Use(middleware.RequestID)
	r.Use(middleware.Logger)
	r.Use(middleware.Recoverer)

	// CORS middleware — must be registered before your route handlers.
	r.Use(cors.Handler(cors.Options{
		// AllowedOrigins accepts a list of allowed origins.
		// Use "*" to allow all origins in development only.
		AllowedOrigins: []string{"https://example.com", "https://app.example.com"},

		// AllowedMethods lists the HTTP methods your API supports.
		AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},

		// AllowedHeaders lists the headers a client can include in a request.
		AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},

		// ExposedHeaders lists response headers the browser is allowed to access.
		ExposedHeaders: []string{"Link"},

		// AllowCredentials permits cookies/auth headers to be sent cross-origin.
		AllowCredentials: true,

		// MaxAge caches the preflight response for the given number of seconds.
		MaxAge: 300,
	}))

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hello"))
	})

	http.ListenAndServe(":3333", r)
}
3
Verify with a preflight request
4
curl -i -X OPTIONS http://localhost:3333/ \
  -H "Origin: https://example.com" \
  -H "Access-Control-Request-Method: POST"
5
A successful preflight returns 204 No Content with the Access-Control-Allow-* headers set by the cors middleware.
Do not use AllowedOrigins: []string{"*"} in production when AllowCredentials: true is set. Browsers block credentialed requests to wildcard origins; use explicit origin lists instead.

Generating route documentation with docgen

docgen traverses a fully configured chi.Router and prints every registered route:
docgen_example.go
package main

import (
	"fmt"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/docgen"
)

func printRoutes(r chi.Router) {
	// Print routes as Markdown.
	fmt.Println(docgen.MarkdownRoutesDoc(r, docgen.MarkdownOpts{
		ProjectPath: "github.com/your-org/your-service",
		Intro:       "API route reference.",
	}))

	// Or as JSON for machine consumption.
	// fmt.Println(docgen.JSONRoutesDoc(r))
}
Pass a -routes flag to your binary and call printRoutes conditionally. This lets CI pipelines generate up-to-date API docs on every build without starting the HTTP server.

Beyond REST

chi is a general-purpose HTTP router — not a REST-only framework. Many teams use it as the foundation layer for other communication protocols.
webrpc is a web-focused RPC framework with code generation for clients and servers. It generates a standard http.Handler that you can mount directly onto a chi router:
webrpc_mount.go
// Mount a generated webrpc handler at /rpc
r.Mount("/rpc", generated.NewMyServiceServer(myServiceImpl, nil))

Community middleware

Beyond the official go-chi organization, the broader net/http ecosystem is fully compatible with chi. Any middleware that accepts and returns an http.Handler works without any adapter or shim. Popular community options include:
PackagePurpose
gorilla/sessionsCookie and filesystem session store
unrolled/secureHTTP security headers (CSP, HSTS, etc.)
felixge/httpsnoopCapture http.ResponseWriter metrics without wrapping
rs/zerologZero-allocation structured JSON logging
If a middleware claims to work with net/http, it works with chi. There are no adapters, no special interfaces, and no registration steps beyond r.Use(myMiddleware).

Build docs developers (and LLMs) love