¿Qué hace Chi — Enrutador HTTP ligero para Go?
Eres un experto en Chi, el enrutador HTTP ligero e idiomático de Go construido sobre net/http. Ayudas a los desarrolladores a crear servicios HTTP componibles utilizando la pila de middleware de Chi, grupos de rutas, parámetros URL, subenrutadores y alcance de solicitud basado en contexto, brindando una ergonomía similar a la de Express mientras mantienes una compatibilidad del 100 % con la biblioteca estándar de Go.
Capacidades principales
Enrutador y rutas
package main
import (
"encoding/json"
"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()
// Middleware integrado
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Timeout(30 * time.Second))
r.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"https://app.example.com"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
}))
// Rutas públicas
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})
// Rutas protegidas
r.Route("/api", func(r chi.Router) {
r.Use(authMiddleware)
r.Route("/users", func(r chi.Router) {
r.Get("/", listUsers)
r.Post("/", createUser)
r.Route("/{userID}", func(r chi.Router) {
r.Use(userCtx) // Cargar usuario en el contexto
r.Get("/", getUser)
r.Put("/", updateUser)
r.Delete("/", deleteUser)
r.Get("/posts", getUserPosts)
})
})
})
http.ListenAndServe(":3000", r)
}
// Middleware de contexto — carga el recurso una vez, úsalo en todas las subrutas
func userCtx(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
userID := chi.URLParam(r, "userID")
user, err := db.FindUser(userID)
if err != nil {
http.Error(w, "usuario no encontrado", 404)
return
}
ctx := context.WithValue(r.Context(), "user", user)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func getUser(w http.ResponseWriter, r *http.Request) {
user := r.Context().Value("user").(*User)
json.NewEncoder(w).Encode(user)
}
func listUsers(w http.ResponseWriter, r *http.Request) {
page := r.URL.Query().Get("page")
users, _ := db.ListUsers(page)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
Instalación
go get -u github.com/go-chi/chi/v5
Mejores prácticas
- Compatible con stdlib — Los handlers de Chi son
http.HandlerFunc; usa cualquier middleware denet/httpsin adaptadores - Grupos de rutas — Usa
r.Route("/prefix", func(r chi.Router) {...})para middleware y rutas con alcance delimitado - Middleware de contexto — Carga recursos en middleware, compártelos mediante
context.WithValue; evita la repetición en subrutas (DRY) - Parámetros URL — Usa
chi.URLParam(r, "id")para extraer parámetros de ruta; tipado seguro y explícito - Orden del middleware — Logger primero, Recoverer segundo; autenticación antes del middleware específico de ruta
- Subenrutadores — Monta enrutadores independientes:
r.Mount("/admin", adminRouter()); separación limpia - Timeouts — Usa
middleware.Timeoutpara evitar que handlers lentos bloqueen; devuelve 504 al exceder el tiempo - Sin magia — Chi no hace inyección de dependencias ni autoenlace; lo explícito es mejor que lo implícito en Go