func newDiscovery(durl, dproxyurl string, id types.ID) (*discovery, error) { u, err := url.Parse(durl) if err != nil { return nil, err } token := u.Path u.Path = "" pf, err := newProxyFunc(dproxyurl) if err != nil { return nil, err } cfg := client.Config{ Transport: &http.Transport{Proxy: pf}, Endpoints: []string{u.String()}, } c, err := client.New(cfg) if err != nil { return nil, err } dc := client.NewKeysAPIWithPrefix(c, "") return &discovery{ cluster: token, c: dc, id: id, url: u, clock: clockwork.NewRealClock(), }, nil }
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. func NewClientHandler(server *etcdserver.EtcdServer) http.Handler { sec := security.NewStore(server, defaultServerTimeout) kh := &keysHandler{ sec: sec, server: server, clusterInfo: server.Cluster, timer: server, timeout: defaultServerTimeout, } sh := &statsHandler{ stats: server, } mh := &membersHandler{ sec: sec, server: server, clusterInfo: server.Cluster, clock: clockwork.NewRealClock(), } dmh := &deprecatedMachinesHandler{ clusterInfo: server.Cluster, } sech := &securityHandler{ sec: sec, clusterInfo: server.Cluster, } mux := http.NewServeMux() mux.HandleFunc("/", http.NotFound) mux.Handle(healthPath, healthHandler(server)) mux.HandleFunc(versionPath, serveVersion) mux.Handle(keysPrefix, kh) mux.Handle(keysPrefix+"/", kh) mux.HandleFunc(statsPrefix+"/store", sh.serveStore) mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) mux.HandleFunc(varsPath, serveVars) mux.Handle(metricsPath, prometheus.Handler()) mux.Handle(membersPrefix, mh) mux.Handle(membersPrefix+"/", mh) mux.Handle(deprecatedMachinesPrefix, dmh) handleSecurity(mux, sech) return mux }
func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") { return } w.Header().Set("X-Etcd-Cluster-ID", h.clusterInfo.ID().String()) ctx, cancel := context.WithTimeout(context.Background(), h.timeout) defer cancel() rr, err := parseKeyRequest(r, clockwork.NewRealClock()) if err != nil { writeError(w, err) return } // The path must be valid at this point (we've parsed the request successfully). if !hasKeyPrefixAccess(h.sec, r, r.URL.Path[len(keysPrefix):]) { writeNoAuth(w) return } resp, err := h.server.Do(ctx, rr) if err != nil { err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) writeError(w, err) return } switch { case resp.Event != nil: if err := writeKeyEvent(w, resp.Event, h.timer); err != nil { // Should never be reached log.Printf("error writing event: %v", err) } case resp.Watcher != nil: ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) defer cancel() handleKeyWatch(ctx, w, resp.Watcher, rr.Stream, h.timer) default: writeError(w, errors.New("received response with no Event/Watcher!")) } }
// The given namespaces will be created as initial directories in the returned store. func New(namespaces ...string) Store { s := newStore(namespaces...) s.clock = clockwork.NewRealClock() return s }