Reputation: 3794
So I want to get rid of one more dependency (gorilla/mux) and use the std http.ServeMux
with it's new routing patterns.
The problem is, that gorilla/mux had this concept of a subrouter, which could handle everything under a specified path.
I needed to serve paths like:
GET /api/user/id
POST /api/user/id
GET /api/product/id
So I had something like:
apirouter := mainRouter.PathPrefix("/api").Subrouter()
users.RegisterHandler(apirouter)
products.RegisterHandler(apirouter)
and then in eg. users
package:
func RegisterHandler(router *mux.Router) {
subrouter := router.PathPrefix("/user").Subrouter()
subrouter.HandleFunc("/{id}", getUser).Methods(http.MethodGet)
subrouter.HandleFunc("/{id}", postUser).Methods(http.MethodPost)
subrouter.HandleFunc("/{id}", updateUser).Methods(http.MethodPut)
}
How could this be achieved with http.ServeMux
? I want to be able to create a subrouter, pass it around and register new routes under it.
Something like this?
func RegisterHandler(router *http.ServeMux) {
subrouter := http.NewServeMux()
router.Handle("/user", someMagicMiddleware(subrouter))
subrouter.HandleFunc("GET /{id}", getUser)
subrouter.HandleFunc("POST /{id}", postUser)
subrouter.HandleFunc("PUT /{id}", updateUser)
}
Upvotes: 2
Views: 2685
Reputation: 3794
Ok so I think I have it:
package httphelp
func Subrouter(router *http.ServeMux, route string) *http.ServeMux {
sr := http.NewServeMux()
route = strings.TrimSuffix(route, "/")
router.Handle(route, removePrefix(sr, route))
router.Handle(route+"/", removePrefix(sr, route))
return sr
}
func removePrefix(h http.Handler, prefix string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
r.URL.Path = "/" + strings.TrimPrefix(strings.TrimPrefix(path, prefix), "/")
h.ServeHTTP(w, r)
r.URL.Path = path
})
}
It creates a new http.ServeMux
which handles all subsequent requests under that prefix. And the sub-paths can be registered independently :)
apirouter := httphelp.Subrouter(mainRouter, "/api")
users.RegisterHandler(apirouter)
products.RegisterHandler(apirouter)
users
package:
func RegisterHandler(router *http.ServeMux) {
subrouter := httphelp.Subrouter(router, "/user")
subrouter.HandleFunc("GET /{id}", getUser)
subrouter.HandleFunc("POST /{id}", postUser)
subrouter.HandleFunc("PUT /{id}", updateUser)
}
Any enhancements welcome :)
Upvotes: 2