Gin: segment conflicts with existing wildcard

Created on 1 Apr 2018  路  6Comments  路  Source: gin-gonic/gin

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!

Most helpful comment

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.

All 6 comments

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.

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.

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...

why not change name? like:

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

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

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")
        ....
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

lilee picture lilee  路  3Comments

ghost picture ghost  路  3Comments

ccaza picture ccaza  路  3Comments

oryband picture oryband  路  3Comments

cxk280 picture cxk280  路  3Comments