DEV Community

Alex Spinov
Alex Spinov

Posted on

Go Chi Has a Free API You're Not Using

Chi is a lightweight HTTP router for Go that's 100% compatible with net/http. It's used by Cloudflare, Heroku, and thousands of production Go services.

The Free APIs You're Missing

1. Middleware Stack — Composable Request Pipeline

import "github.com/go-chi/chi/v5/middleware"

r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(30 * time.Second))
r.Use(middleware.Compress(5))
r.Use(middleware.Throttle(100)) // Max 100 concurrent requests
Enter fullscreen mode Exit fullscreen mode

2. Route Groups — Organized API

r.Route("/api/v1", 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)
            r.Get("/", getUser)
            r.Put("/", updateUser)
            r.Delete("/", deleteUser)
            r.Get("/posts", getUserPosts)
        })
    })

    r.Mount("/admin", adminRouter())
})
Enter fullscreen mode Exit fullscreen mode

3. Context — Type-Safe Request Values

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, "User not found", 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)
}
Enter fullscreen mode Exit fullscreen mode

4. render — JSON Response Helper

import "github.com/go-chi/render"

type UserResponse struct {
    *User
    Elapsed int64 `json:"elapsed"`
}

func (u *UserResponse) Render(w http.ResponseWriter, r *http.Request) error {
    u.Elapsed = time.Since(start).Milliseconds()
    return nil
}

func getUser(w http.ResponseWriter, r *http.Request) {
    user := r.Context().Value("user").(*User)
    render.Render(w, r, &UserResponse{User: user})
}
Enter fullscreen mode Exit fullscreen mode

5. Walk — Introspect All Routes

chi.Walk(r, func(method, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
    fmt.Printf("%-6s %s\n", method, route)
    return nil
})
// Output:
// GET    /api/v1/users
// POST   /api/v1/users
// GET    /api/v1/users/{userID}
Enter fullscreen mode Exit fullscreen mode

Generate API docs, verify routes in tests, debug middleware chains.

Getting Started

go get github.com/go-chi/chi/v5
Enter fullscreen mode Exit fullscreen mode

Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com

Check out my awesome-web-scraping list for the best scraping tools and resources.

Top comments (0)