go 53 lines · 8 steps

Layering route groups and middleware in Gin

A Gin router builds nested groups so authentication and role checks apply exactly where they're needed.

Explained by highlit
1package api
2 
3func RegisterRoutes(r *gin.Engine, deps *Dependencies) {
4 r.GET("/health", func(c *gin.Context) {
5 c.JSON(http.StatusOK, gin.H{"status": "ok"})
6 })
7 
8 v1 := r.Group("/api/v1")
9 v1.POST("/login", deps.AuthHandler.Login)
10 v1.POST("/register", deps.AuthHandler.Register)
11 
12 authed := v1.Group("")
13 authed.Use(RequireAuth(deps.TokenService))
14 {
15 authed.GET("/me", deps.UserHandler.CurrentUser)
16 
17 projects := authed.Group("/projects")
18 {
19 projects.GET("", deps.ProjectHandler.List)
20 projects.POST("", deps.ProjectHandler.Create)
21 projects.GET("/:id", deps.ProjectHandler.Show)
22 projects.DELETE("/:id", deps.ProjectHandler.Delete)
23 }
24 
25 admin := authed.Group("/admin")
26 admin.Use(RequireRole("admin"))
27 {
28 admin.GET("/users", deps.AdminHandler.ListUsers)
29 admin.PATCH("/users/:id/ban", deps.AdminHandler.BanUser)
30 }
31 }
32}
33 
34func RequireAuth(tokens *TokenService) gin.HandlerFunc {
35 return func(c *gin.Context) {
36 header := c.GetHeader("Authorization")
37 token := strings.TrimPrefix(header, "Bearer ")
38 if token == header || token == "" {
39 c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing bearer token"})
40 return
41 }
42 
43 claims, err := tokens.Verify(c.Request.Context(), token)
44 if err != nil {
45 c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid or expired token"})
46 return
47 }
48 
49 c.Set("userID", claims.Subject)
50 c.Set("role", claims.Role)
51 c.Next()
52 }
53}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Route groups let you attach middleware once and have it cover every nested endpoint.
  2. 2Middleware that calls Abort short-circuits the chain so protected handlers never run.
  3. 3Stashing verified claims in the request context passes auth data cleanly to downstream handlers.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Layering route groups and middleware in Gin — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code