Go with the Flow: Navigating HTTP Services with chi


In Go (Golang), chi
is a lightweight, idiomatic and composable router for building HTTP services. It's designed to offer the power and flexibility of the standard library net/http
package while providing a clean API for building complex applications with less code and more clarity.
Here are some of the key features and benefits of using chi
:
Lightweight and Idiomatic:
chi
is designed to be simple and straightforward, sticking closely to Go's standard library idioms. This makes it easy to learn and integrate into existing Go projects.Composability:
chi
allows you to build middleware and routes in a highly composable way. You can define routes and middlewares in a tree-like structure, enabling modular and reusable code.Middleware Support:
chi
supports middleware out-of-the-box, allowing you to add functionalities like logging, authentication, and request validation easily.Context Aware:
chi
is built on top of Go's context package, enabling you to pass request-scoped values, deadlines, and cancellations across API boundaries and goroutines.Performance:
chi
is designed with performance in mind, providing minimal overhead while offering powerful routing capabilities.
Example Usage
Here's a basic example of how to use chi
to set up a simple web server:
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
// Use some middleware
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
// Define routes
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome to the home page!"))
})
r.Get("/hello", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
// Start the server
http.ListenAndServe(":8080", r)
}
Setting Up Middleware
Middleware in chi
can be applied globally to all routes or locally to specific routes or groups of routes. Here's an example:
// Applying middleware globally
r.Use(middleware.Logger)
// Applying middleware to specific routes
r.With(middleware.BasicAuth("myRealm", map[string]string{"user": "password"})).
Get("/secure", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("This is a secure endpoint"))
})
Nested Routes and Groups
You can also create nested routes and groups for better organization:
coder.Route("/admin", func(r chi.Router) {
r.Use(AdminOnly) // Apply middleware specific to this group
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Admin home"))
})
r.Get("/dashboard", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Admin dashboard"))
})
})
URL Parameters
chi
allows you to define routes with parameters:
coder.Get("/user/{userID}", func(w http.ResponseWriter, r *http.Request) {
userID := chi.URLParam(r, "userID")
w.Write([]byte("User ID: " + userID))
})
Handling Subroutes
Subroutes can be defined to handle nested routing structures:
coder.Route("/api", func(r chi.Router) {
r.Get("/users", listUsers)
r.Get("/users/{userID}", getUser)
r.Post("/users", createUser)
})
Middleware Example
Here's an example of a custom middleware that logs the request duration:
codefunc requestDurationLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
log.Printf("Request %s took %v", r.URL.Path, duration)
})
}
// Applying the custom middleware
r.Use(requestDurationLogger)
Take-away
chi
is a lightweight, idiomatic, and composable Go router for building HTTP services. It offers middleware support, context awareness, and high performance. Its simple API allows for modular and reusable code, making it a powerful choice for developing complex web applications efficiently.
Image attribution
Subscribe to my newsletter
Read articles from Nikhil Akki directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Nikhil Akki
Nikhil Akki
I am a Full Stack Solution Architect at Deloitte LLP. I help build production grade web applications on major public clouds - AWS, GCP and Azure.