Handle Integer IDs in Go Chi Path Parameters

Handling integer IDs in a URL can become tedious very quickly when the amount of endpoints using those IDs becomes large. Here is a way to handle integer path parameters easily by utilizing middleware in the go-chi package. The middleware gets a named path parameter from the request as a string, then attempts to parse the string into an integer. In case there is an error, we return a 400. Otherwise we place the parsed integer into the request context and continuing serving the request in the next handler.

type ctxKey string

func (ck ctxKey) String() string {
	return string(ck)
}

func URLIDMiddleware(name string) func(next http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			idStr := chi.URLParam(r, name)
			id, err := strconv.Atoi(idStr)
			if err != nil {
                log.Printf("err converting ID to integer: %+v\n", err)
                // handle error by returning 400 - bad request, or by redirecting
                // to an error page, or rendering an error
				return
			}
			next.ServeHTTP(
                w, r.WithContext(
                    context.WithValue(r.Context(), ctxKey(name), id)))
		})
	}
}

We can also create a utility function to retrieve the named ID from request context:

func GetURLID(r *http.Request, name string) int {
	return r.Context().Value(ctxKey(name)).(int)
}

As an example, we can create a simple web server:

package main

import (
    "github.com/go-chi/chi/v5"
)

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

    r.Route("/{itemID}", func (r chi.Router) {
        r.Use(URLIDMiddleware("itemID"))
        r.Get("/", func(w http.ResponseWriter, r *http.Request) {
            itemID := GetURLID(r, "itemID")
        })
    })

    http.ListenAndServe(":8080", r)
}

This is a nice way to simplify retrieving an integer ID from the URL. Of course, if we’re using integer IDs directly in our URLs, we must make sure that our endpoints are protected from unauthorized access, but that is topic of its own.

Sign up or log in to start commenting