go 30 lines · 7 steps

Validating URI params in a Gin handler

A Gin route binds and validates path parameters into a struct before touching the data store, then maps errors to precise HTTP status codes.

Explained by highlit
1package handlers
2 
3type BookURI struct {
4 Collection string `uri:"collection" binding:"required,alphanum"`
5 ID string `uri:"id" binding:"required,uuid"`
6}
7 
8func GetBook(c *gin.Context) {
9 var params BookURI
10 if err := c.ShouldBindUri(&params); err != nil {
11 c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
12 return
13 }
14 
15 book, err := store.FindBook(c.Request.Context(), params.Collection, params.ID)
16 if errors.Is(err, ErrBookNotFound) {
17 c.JSON(http.StatusNotFound, gin.H{"error": "book not found"})
18 return
19 }
20 if err != nil {
21 c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load book"})
22 return
23 }
24 
25 c.JSON(http.StatusOK, book)
26}
27 
28func RegisterBookRoutes(r *gin.Engine) {
29 r.GET("/collections/:collection/books/:id", GetBook)
30}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Struct tags let you declare validation rules once and enforce them at bind time instead of writing manual checks.
  2. 2Distinguishing a not-found error from a generic failure lets you return the right status code to the client.
  3. 3Validating and rejecting bad input before hitting the data store keeps invalid requests cheap and the store code clean.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Validating URI params in a Gin handler — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code