I found a few other issues that look like they are related to this problem, but they are all closed and I'm not sure what the status of this bug is, so I'm making a new issue here...

As an example I've defined two routes, one to get a user by their ID, and another to get a user by their email:

    apiRoutes := r.Engine.Group("/api")
    apiRoutes.GET("/users/:id", GetUser)
    apiRoutes.GET("/users/email/:email", GetUser)

When I try and build, I get this error:

panic: path segment 'email/:email' conflicts with existing wildcard ':id' in path '/api/users/email/:email'

The problem is that these routes are NOT ambiguous and shouldn't conflict. I'm using Gin in several APIs and run into this problem in all of them in various ways. The above code is just a simplified demonstration of the bug.

Based on the closed issues I've found here: https://github.com/gin-gonic/gin/issues/205 https://github.com/gin-gonic/gin/issues/388

That last issue referenced this open issue in httprouter: https://github.com/julienschmidt/httprouter/issues/73

...but that issue hasn't been updated since 2015...

So it seems the Gin team is aware of this bug, but it isn't clear whether or not it's going to be fixed. I'm just posting this to get some clarity on the problem.

Thanks!

Comment From: nazwa

Hi @68696c6c - it's not really a bug, but a known limitation. The downside of not using regular expressions for route matching is that paths have to be unique.

Unfortunately afaik this behavior is not going to change any time soon.

Comment From: 68696c6c

Understood, thank you.

However, I was fiddling with this more today and found a workaround that I wanted to share here in case anyone else comes across this issue.

If I change my routes to look like this, everything works fine:

        apiRoutes := r.Engine.Group("/api")
    apiRoutes.GET("/users/:id", GetUser)
    apiRoutes.GET("/users/:id/email", GetUserByEmail)

Basically, both routes need to have the wildcard in the same position, and the wildcards need to be named the same thing.

Comment From: davexpro

Understood, thank you.

However, I was fiddling with this more today and found a workaround that I wanted to share here in case anyone else comes across this issue.

If I change my routes to look like this, everything works fine:

apiRoutes := r.Engine.Group("/api") apiRoutes.GET("/users/:id", GetUser) apiRoutes.GET("/users/:id/email", GetUserByEmail) Basically, both routes need to have the wildcard in the same position, and the wildcards need to be named the same thing.

Do you have some good alternatives?

I encounter the same problem...

Comment From: thinkerou

why not change name? like:

apiRoutes := r.Engine.Group("/api/users")
apiRoutes.GET("/byid/:id", GetUser)
apiRoutes.GET("/byemail/:id", GetUserByEmail)

Comment From: djumpen

I needed such routes:

POST /users
GET /users/:id
GET /users/:id/status
POST /users/actions/some-action // panic

I have to switch to the next model:

POST /users
GET /users/user/:id
GET /users/user/:id/status
POST /users/actions/some-action

Comment From: vchakoshy

Router:

r.GET("/auth/user/:id/", badUserSearchHandler)
// r.GET("/auth/user/search/", badUserSearchHandler)

bad Function

func badUserSearchHandler(c *gin.Context) {
    id := c.Param("id")
    if id == "search" {
        searchUser(c)
        return
    }
    userItem(c)
}
func searchUser(c *gin.Context) {
    qInput := strings.TrimSpace(c.Query("q"))
        .....
}
func userItem(c *gin.Context) {
    id := c.Param("id")
        ....
}

Comment From: kuchaguangjie

Any solution yet? GET /:id and GET /count conflict, it's a very common requirement,

Comment From: Andro999b

Why this closed? GIN route matching is super ugly.

Comment From: pavelpatrin

There was a PR to improve httprouter used by gin: https://github.com/julienschmidt/httprouter/pull/329. Maybe we can ask @rw-access and @julienschmidt there to go forward with it. Maybe start some crowdfunding to get it released?

Comment From: pavelpatrin

Guys?