How to handl these routes in go httprouter: /hello/:name and /hello/b/c?

616 views Asked by At

httprouter does not allow this and panics when start.

httprouter :panic: wildcard route ':name' conflicts with existing children in path '/hello/:name'.

In my understanding,
"/hello/:name" has two parts ,but /hello/b/c has three parts.
"/hello/:name" will match any url has two parts which prefix /hello
"/hello/b/c" only match /hello/b/c

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/julienschmidt/httprouter"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "Welcome!\n")
}

func Index2(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "Welcome222!\n")
}

func main() {
    router := httprouter.New()
    router.GET("/hello/b/c", Index2)

    router.GET("/hello/:name", Index)

    log.Fatal(http.ListenAndServe(":8080", router))
}
2

There are 2 answers

0
dave On

You could remove the line router.GET("/hello/b/c", Index2) and then have:

func Index(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
    if strings.HasPrefix(ps.ByName("name"), "b/c") {
        return Index2(w, r, ps)
    } else {
        fmt.Fprint(w, "Welcome!\n")
    }
}
0
Jiulin Teng On

It's very inconvenient, as I have found, too. There isn't a great solution.

Two things can be found:

  1. Make a fork of httprouter and modify tree.go (on first glance, this seems to be it).
  2. Use the "catch-all" wildcard *name and handle the route in your own function with an early return.

Which is preferable depends on how many of this type of routes exist, but 2 is probably better.