Search code examples
goroutesgo-gin

Go Gin-Gonic Handle Not Found for Route Group


I was wondering how to get a Go Gin-Gonic Web Server to handle Not Found Routes for a specific Group. If I have the following Code :

func main() {
    r := gin.Default()

    // handle /sub routes

    rGroup := r.Group("/sub")
    {
        rGroup.GET("/a", func(c *gin.Context) {
            // respond found /sub/a
        })

        rGroup.NoRoute(func(c *gin.Context) { // this fails, NoRoute is not available
            // respond not found in /sub
        })
    }

    // handle / routes

    r.GET("/a", func(c *gin.Context) {
        // respond found /a
    })

    r.NoRoute(func(c *gin.Context) {
        // respond not found in /
    })

    r.Run(":8000")
}

Then it is working for the / routes but the Group does not have the NoRoute Method so is there another way to achieve the same thing?


Solution

  • Gin does support this. Inside the NoRoute, You can do different logic based the gin.Context and return different results.
    

    After conducting some research, it appears that Gin currently does not support this directly. Instead, it can be achieved in a different way using NoRoute

    Here is a sample implementation; I hope this helps.

    package main
    
    import (
        "net/http"
        "strings"
    
        "github.com/gin-gonic/gin"
    )
    
    func notFoundHandler(c *gin.Context) {
        // check the path is /sub
        if strings.HasPrefix(c.Request.URL.Path, "/sub/") {
            c.JSON(http.StatusNotFound, gin.H{"message": "Route not found in /sub"})
            c.Abort()
        }
    
        // check the path is /v1
        if strings.HasPrefix(c.Request.URL.Path, "/v1/") {
            c.JSON(http.StatusNotFound, gin.H{"message": "Route not found in /v1"})
            c.Abort()
        }
    }
    
    func main() {
        r := gin.Default()
        v1 := r.Group("/v1")
        {
    
            v1.GET("/a", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "inside v1 a"})
                return
            })
    
        }
    
        rGroup := r.Group("/sub")
        {
    
            rGroup.GET("/a", func(c *gin.Context) {
                c.JSON(200, gin.H{"message": "inside sub a"})
                return
            })
    
        }
        r.NoRoute(notFoundHandler)
    
        r.Run(":8000")
    }
    
    

    Reference :