Search code examples
httpgogorillamux

Mount double http routers in Go


I'm trying to mount 2 http routeurs such as:

    http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    })

    r := mux.NewRouter()
    r.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "hi, %q", html.EscapeString(r.URL.Path))
    })

    http.Handle("/subpath", r)

    log.Fatal(http.ListenAndServe(":8080", nil))

However /subpath/foo returns 404 page not found. I'm trying to get a specific router for a specific subpath but this does not seem to work. It only works if I mount it on the root / and have the mux router parsing the entire Path. Ideally, I'd like the mux router to only deal with the path relative to its own root. Is it something doable?


Solution

  • 2 things.

    First, you have to register the "subrouter" for a path ending with slash: /subpath/, else only the /subpath path would be routed to it, but not the complete subree.

    Second, your r router routes the /foo path to the registered function, but the actual path will be /subpath/foo which does not match /foo so it will not be routed to it. You have to strip the /subpath prefix.

    Working code:

    http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    })
    
    r := mux.NewRouter()
    r.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "hi, %q", html.EscapeString(r.URL.Path))
    })
    
    http.Handle("/subpath/", http.StripPrefix("/subpath", r))
    
    log.Fatal(http.ListenAndServe(":8080", nil))
    

    Edit: I think I found a possible duplicate (it uses the standard lib's ServeMux, but the same principle applies): Put http.NewServeMux into http.NewServeMux