From fd368e5e5fa85f759408008347733386d8794e8f Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Wed, 6 Apr 2016 14:35:41 +0100 Subject: [PATCH] Unhack dealing with slashed in node names. --- app/api_report_test.go | 5 ++-- app/api_topologies.go | 4 ++-- app/api_topologies_test.go | 4 ++-- app/api_topology.go | 34 ++++++++++++++------------- app/router.go | 48 ++++++++++---------------------------- prog/app.go | 12 ++++++++-- 6 files changed, 47 insertions(+), 60 deletions(-) diff --git a/app/api_report_test.go b/app/api_report_test.go index 661017feb..98c32e2d4 100644 --- a/app/api_report_test.go +++ b/app/api_report_test.go @@ -12,8 +12,9 @@ import ( ) func topologyServer() *httptest.Server { - handler := app.TopologyHandler(StaticReport{}, mux.NewRouter(), nil) - return httptest.NewServer(handler) + router := mux.NewRouter() + app.RegisterTopologyRoutes(StaticReport{}, router) + return httptest.NewServer(router) } func TestAPIReport(t *testing.T) { diff --git a/app/api_topologies.go b/app/api_topologies.go index 71aa66ca7..e152dc12a 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -307,9 +307,9 @@ func (r *registry) captureRenderer(rep Reporter, f reportRenderHandler) CtxHandl } } -func (r *registry) captureRendererWithoutFilters(rep Reporter, topologyID string, f reportRenderHandler) CtxHandlerFunc { +func (r *registry) captureRendererWithoutFilters(rep Reporter, f reportRenderHandler) CtxHandlerFunc { return func(ctx context.Context, w http.ResponseWriter, req *http.Request) { - topology, ok := r.get(topologyID) + topology, ok := r.get(mux.Vars(req)["topology"]) if !ok { http.NotFound(w, req) return diff --git a/app/api_topologies_test.go b/app/api_topologies_test.go index 968525202..346d2f9e1 100644 --- a/app/api_topologies_test.go +++ b/app/api_topologies_test.go @@ -54,8 +54,8 @@ func TestAPITopologyAddsKubernetes(t *testing.T) { router := mux.NewRouter() c := app.NewCollector(1 * time.Minute) app.RegisterReportPostHandler(c, router) - handler := app.TopologyHandler(c, router, nil) - ts := httptest.NewServer(handler) + app.RegisterTopologyRoutes(c, router) + ts := httptest.NewServer(router) defer ts.Close() body := getRawJSON(t, ts, "/api/topology") diff --git a/app/api_topology.go b/app/api_topology.go index 712b6d7f4..e05b385b2 100644 --- a/app/api_topology.go +++ b/app/api_topology.go @@ -5,6 +5,7 @@ import ( "time" log "github.com/Sirupsen/logrus" + "github.com/gorilla/mux" "golang.org/x/net/context" "github.com/weaveworks/scope/common/xfer" @@ -56,23 +57,24 @@ func handleWs(ctx context.Context, rep Reporter, renderer render.Renderer, w htt } // Individual nodes. -func handleNode(topologyID, nodeID string) func(context.Context, Reporter, render.Renderer, http.ResponseWriter, *http.Request) { - return func(ctx context.Context, rep Reporter, renderer render.Renderer, w http.ResponseWriter, r *http.Request) { - var ( - report, err = rep.Report(ctx) - rendered = renderer.Render(report) - node, ok = rendered[nodeID] - ) - if err != nil { - respondWith(w, http.StatusInternalServerError, err.Error()) - return - } - if !ok { - http.NotFound(w, r) - return - } - respondWith(w, http.StatusOK, APINode{Node: detailed.MakeNode(topologyID, report, rendered, node)}) +func handleNode(ctx context.Context, rep Reporter, renderer render.Renderer, w http.ResponseWriter, r *http.Request) { + var ( + vars = mux.Vars(r) + topologyID = vars["topology"] + nodeID = vars["id"] + report, err = rep.Report(ctx) + rendered = renderer.Render(report) + node, ok = rendered[nodeID] + ) + if err != nil { + respondWith(w, http.StatusInternalServerError, err.Error()) + return } + if !ok { + http.NotFound(w, r) + return + } + respondWith(w, http.StatusOK, APINode{Node: detailed.MakeNode(topologyID, report, rendered, node)}) } func handleWebsocket( diff --git a/app/router.go b/app/router.go index 08aba0ba5..986b61ce0 100644 --- a/app/router.go +++ b/app/router.go @@ -88,44 +88,20 @@ func gzipHandler(h http.HandlerFunc) http.HandlerFunc { // Routes which should be matched before the topology routes should be added // to a router and passed in preRoutes. Routes to be matches after topology // routes should be added to a router and passed to postRoutes. -func TopologyHandler(c Reporter, preRoutes *mux.Router, postRoutes http.Handler) http.Handler { - get := preRoutes.Methods("GET").Subrouter() - get.HandleFunc("/api", gzipHandler(requestContextDecorator(apiHandler))) - get.HandleFunc("/api/topology", gzipHandler(requestContextDecorator(topologyRegistry.makeTopologyList(c)))) +func RegisterTopologyRoutes(router *mux.Router, r Reporter) { + get := router.Methods("GET").Subrouter() + get.HandleFunc("/api", + gzipHandler(requestContextDecorator(apiHandler))) + get.HandleFunc("/api/topology", + gzipHandler(requestContextDecorator(topologyRegistry.makeTopologyList(r)))) get.HandleFunc("/api/topology/{topology}", - gzipHandler(requestContextDecorator(topologyRegistry.captureRenderer(c, handleTopology)))) + gzipHandler(requestContextDecorator(topologyRegistry.captureRenderer(r, handleTopology)))) get.HandleFunc("/api/topology/{topology}/ws", - requestContextDecorator(topologyRegistry.captureRenderer(c, handleWs))) // NB not gzip! - get.HandleFunc("/api/report", gzipHandler(requestContextDecorator(makeRawReportHandler(c)))) - - // We pull in the http.DefaultServeMux to get the pprof routes - preRoutes.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux) - - if postRoutes != nil { - preRoutes.PathPrefix("/").Handler(postRoutes) - } - - // We have to handle the node details path manually due to - // various bugs in gorilla.mux and Go URL parsing. See #804. - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - vars, match := matchURL(r, "/api/topology/{topology}/{id}") - if !match { - preRoutes.ServeHTTP(w, r) - return - } - - topologyID := vars["topology"] - nodeID := vars["id"] - if nodeID == "ws" { - preRoutes.ServeHTTP(w, r) - return - } - - handler := gzipHandler(requestContextDecorator(topologyRegistry.captureRendererWithoutFilters( - c, topologyID, handleNode(topologyID, nodeID), - ))) - handler.ServeHTTP(w, r) - }) + requestContextDecorator(topologyRegistry.captureRenderer(r, handleWs))) // NB not gzip! + get.MatcherFunc(URLMatcher("/api/topology/{topology}/{id}")).HandlerFunc( + gzipHandler(requestContextDecorator(topologyRegistry.captureRendererWithoutFilters(r, handleNode)))) + get.HandleFunc("/api/report", + gzipHandler(requestContextDecorator(makeRawReportHandler(r)))) } // RegisterReportPostHandler registers the handler for report submission diff --git a/prog/app.go b/prog/app.go index cdcff684b..5669e9a04 100644 --- a/prog/app.go +++ b/prog/app.go @@ -28,11 +28,19 @@ import ( // Router creates the mux for all the various app components. func router(collector app.Collector, controlRouter app.ControlRouter, pipeRouter app.PipeRouter) http.Handler { - router := mux.NewRouter() + router := mux.NewRouter().SkipClean(true) + + // We pull in the http.DefaultServeMux to get the pprof routes + router.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux) + app.RegisterReportPostHandler(collector, router) app.RegisterControlRoutes(router, controlRouter) app.RegisterPipeRoutes(router, pipeRouter) - return app.TopologyHandler(collector, router, http.FileServer(FS(false))) + app.RegisterTopologyRoutes(router, collector) + + router.PathPrefix("/").Handler(http.FileServer(FS(false))) + + return router } func awsConfigFromURL(url *url.URL) *aws.Config {