I like checking out other projects on github to get ideas on how to do things, and for these cases, I usually look at the Docker repo first . So they do it:
For system routes, define all handlers in system_routes.go , and then initialize these routes with the NewRouter function in system.go .
type systemRouter struct { backend Backend routes []router.Route } func NewRouter(b Backend) router.Router { r := &systemRouter{ backend: b, } r.routes = []router.Route{ local.NewOptionsRoute("/", optionsHandler), local.NewGetRoute("/_ping", pingHandler), local.NewGetRoute("/events", r.getEvents), local.NewGetRoute("/info", r.getInfo), local.NewGetRoute("/version", r.getVersion), local.NewPostRoute("/auth", r.postAuth), } return r }
Note that systemRouter implements the router.Router interface, and the Routes function returns [] router.Route, and their handlers are defined as
func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
instead of the standard HTTP Go handler:
func(w http.ResponseWriter, r *http.Request)
So, there is additional code to convert the Docker API handler to an HTTP traffic handler in makeHttpHandler .
And finally, to add these routes to their multiplexer, on server.go they implement several other functions to add middleware to their handlers.
If this is what you think is what you are looking for, then take the time to analyze the Docker code for your routes, and if you need me to develop more or miss something, post a comment.