Search code examples
gogo-gin

How to add different endpoints with the same path prefix and param in Gin?



I have built an API in Go using the Gin framework. I have one route in API where I can get users with id. But now I also want to get users by their username. So I tried the same way which I did for getting users with id. But it is giving me an error during compile. Can you guys please tell me how can I do that?
Thank you.
Routes -

grp.GET("/users", controllers.GetUsers)
grp.GET("/users/:id", controllers.GetUser)
grp.GET("/users/:username", controllers.GetUserByUsername)   //error - panic: ':username' in new path '/users/:username' conflicts with existing wildcard ':id' in existing prefix '/users/:id'
grp.POST("/users", controllers.CreateUser)
grp.PATCH("/users/:id", controllers.UpdateUser)
grp.DELETE("/users/:id", controllers.DeleteUser)

Controller -

func GetUser(c *gin.Context) {
    paramID := c.Params.ByName("id")

    ctx := context.Background()
    sa := option.WithCredentialsFile(firestoreFilePath)
    app, err := firebase.NewApp(ctx, nil, sa)
    if err != nil {
        log.Fatalln(err)
    }

    client, err := app.Firestore(ctx)
    if err != nil {
        log.Fatalln(err)
    }
    defer client.Close()

    dsnap, err := client.Collection("users").Doc(paramID).Get(ctx)
    if err != nil {
        fmt.Print(err)
        c.IndentedJSON(http.StatusNotFound, gin.H{
            "message": "User not found",
        })
        return
    }
    m := dsnap.Data()

    c.IndentedJSON(http.StatusNotFound, gin.H{
        "User":    m,
        "message": "User returned successfully",
    })

}

API response -

[
  {
     "id": 1,
     "name": "Leanne Graham",
     "username": "Bret",
     "email": "Sincere@april.biz",
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
  },
  {
    "id": 3,
    "name": "Clementine Bauch",
    "username": "Samantha",
    "email": "Nathan@yesenia.net",
  }
]

Solution

  • This is a known limitation in gin. You'll have to make all paths unique. Like adding a prefix as below:

    grp.GET("/users/username/:username", controllers.GetUserByUsername)
    

    There's more info on this issue thread: https://github.com/gin-gonic/gin/issues/1301