mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-05 03:01:11 +00:00
- Add interfaces to allow for alternative implementations for Collector, ControlRouter and PipeRouter. - Pass contexts on http handlers to these interfaces. Although not used by the current (local, in-memory) implementations, the idea is this will be used to pass headers to implementations which support multitenancy (by, for instance, putting an authenticating reverse proxy in form of the app, and then inspecting the headers of the request for a used id).
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package app
|
|
|
|
import (
|
|
"net/http"
|
|
"net/rpc"
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
"github.com/gorilla/mux"
|
|
"golang.org/x/net/context"
|
|
|
|
"github.com/weaveworks/scope/common/xfer"
|
|
)
|
|
|
|
// RegisterControlRoutes registers the various control routes with a http mux.
|
|
func RegisterControlRoutes(router *mux.Router, cr ControlRouter) {
|
|
router.Methods("GET").Path("/api/control/ws").
|
|
HandlerFunc(requestContextDecorator(handleProbeWS(cr)))
|
|
router.Methods("POST").MatcherFunc(URLMatcher("/api/control/{probeID}/{nodeID}/{control}")).
|
|
HandlerFunc(requestContextDecorator(handleControl(cr)))
|
|
}
|
|
|
|
// handleControl routes control requests from the client to the appropriate
|
|
// probe. Its is blocking.
|
|
func handleControl(cr ControlRouter) CtxHandlerFunc {
|
|
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
vars = mux.Vars(r)
|
|
probeID = vars["probeID"]
|
|
nodeID = vars["nodeID"]
|
|
control = vars["control"]
|
|
)
|
|
result, err := cr.Handle(ctx, probeID, xfer.Request{
|
|
AppID: UniqueID,
|
|
NodeID: nodeID,
|
|
Control: control,
|
|
})
|
|
if err != nil {
|
|
respondWith(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
if result.Error != "" {
|
|
respondWith(w, http.StatusBadRequest, result.Error)
|
|
return
|
|
}
|
|
respondWith(w, http.StatusOK, result)
|
|
}
|
|
}
|
|
|
|
// handleProbeWS accepts websocket connections from the probe and registers
|
|
// them in the control router, such that HandleControl calls can find them.
|
|
func handleProbeWS(cr ControlRouter) CtxHandlerFunc {
|
|
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
|
probeID := r.Header.Get(xfer.ScopeProbeIDHeader)
|
|
if probeID == "" {
|
|
respondWith(w, http.StatusBadRequest, xfer.ScopeProbeIDHeader)
|
|
return
|
|
}
|
|
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Printf("Error upgrading control websocket: %v", err)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
codec := xfer.NewJSONWebsocketCodec(conn)
|
|
client := rpc.NewClientWithCodec(codec)
|
|
defer client.Close()
|
|
|
|
id, err := cr.Register(ctx, probeID, func(req xfer.Request) xfer.Response {
|
|
var res xfer.Response
|
|
if err := client.Call("control.Handle", req, &res); err != nil {
|
|
return xfer.ResponseError(err)
|
|
}
|
|
return res
|
|
})
|
|
if err != nil {
|
|
respondWith(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
defer cr.Deregister(ctx, probeID, id)
|
|
codec.WaitForReadError()
|
|
}
|
|
}
|