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.