mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #1423 from bcwaldon/http-refactor-hdlrs
eradicate serverHandler
This commit is contained in:
commit
f9af07eb5b
@ -49,28 +49,46 @@ const (
|
|||||||
|
|
||||||
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
|
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests.
|
||||||
func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
|
func NewClientHandler(server *etcdserver.EtcdServer) http.Handler {
|
||||||
sh := &serverHandler{
|
kh := &keysHandler{
|
||||||
|
server: server,
|
||||||
|
timer: server,
|
||||||
|
timeout: defaultServerTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
sh := &statsHandler{
|
||||||
|
stats: server,
|
||||||
|
}
|
||||||
|
|
||||||
|
amh := &adminMembersHandler{
|
||||||
server: server,
|
server: server,
|
||||||
clusterInfo: server.Cluster,
|
clusterInfo: server.Cluster,
|
||||||
stats: server,
|
|
||||||
timer: server,
|
|
||||||
timeout: defaultServerTimeout,
|
|
||||||
clock: clockwork.NewRealClock(),
|
clock: clockwork.NewRealClock(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dmh := &deprecatedMachinesHandler{
|
||||||
|
clusterInfo: server.Cluster,
|
||||||
|
}
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc(keysPrefix, sh.serveKeys)
|
|
||||||
mux.HandleFunc(keysPrefix+"/", sh.serveKeys)
|
|
||||||
mux.HandleFunc(statsPrefix+"/store", sh.serveStoreStats)
|
|
||||||
mux.HandleFunc(statsPrefix+"/self", sh.serveSelfStats)
|
|
||||||
mux.HandleFunc(statsPrefix+"/leader", sh.serveLeaderStats)
|
|
||||||
mux.HandleFunc(deprecatedMachinesPrefix, sh.serveMachines)
|
|
||||||
mux.HandleFunc(adminMembersPrefix, sh.serveAdminMembers)
|
|
||||||
mux.HandleFunc(versionPrefix, sh.serveVersion)
|
|
||||||
mux.HandleFunc("/", http.NotFound)
|
mux.HandleFunc("/", http.NotFound)
|
||||||
|
mux.HandleFunc(versionPrefix, 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.Handle(adminMembersPrefix, amh)
|
||||||
|
mux.Handle(deprecatedMachinesPrefix, dmh)
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveKeys(w http.ResponseWriter, r *http.Request) {
|
type keysHandler struct {
|
||||||
|
server etcdserver.Server
|
||||||
|
timer etcdserver.RaftTimer
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET", "PUT", "POST", "DELETE") {
|
if !allowMethod(w, r.Method, "GET", "PUT", "POST", "DELETE") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -106,8 +124,11 @@ func (h serverHandler) serveKeys(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveMachines responds address list in the format '0.0.0.0, 1.1.1.1'.
|
type deprecatedMachinesHandler struct {
|
||||||
func (h serverHandler) serveMachines(w http.ResponseWriter, r *http.Request) {
|
clusterInfo etcdserver.ClusterInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *deprecatedMachinesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET", "HEAD") {
|
if !allowMethod(w, r.Method, "GET", "HEAD") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -115,7 +136,13 @@ func (h serverHandler) serveMachines(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(strings.Join(endpoints, ", ")))
|
w.Write([]byte(strings.Join(endpoints, ", ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveAdminMembers(w http.ResponseWriter, r *http.Request) {
|
type adminMembersHandler struct {
|
||||||
|
server etcdserver.Server
|
||||||
|
clusterInfo etcdserver.ClusterInfo
|
||||||
|
clock clockwork.Clock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *adminMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET", "POST", "DELETE") {
|
if !allowMethod(w, r.Method, "GET", "POST", "DELETE") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -188,7 +215,11 @@ func (h serverHandler) serveAdminMembers(w http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveStoreStats(w http.ResponseWriter, r *http.Request) {
|
type statsHandler struct {
|
||||||
|
stats etcdserver.Stats
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *statsHandler) serveStore(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -196,7 +227,7 @@ func (h serverHandler) serveStoreStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(h.stats.StoreStats())
|
w.Write(h.stats.StoreStats())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveSelfStats(w http.ResponseWriter, r *http.Request) {
|
func (h *statsHandler) serveSelf(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -204,7 +235,7 @@ func (h serverHandler) serveSelfStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write(h.stats.SelfStats())
|
w.Write(h.stats.SelfStats())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveLeaderStats(w http.ResponseWriter, r *http.Request) {
|
func (h *statsHandler) serveLeader(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -212,7 +243,7 @@ func (h serverHandler) serveLeaderStats(w http.ResponseWriter, r *http.Request)
|
|||||||
w.Write(h.stats.LeaderStats())
|
w.Write(h.stats.LeaderStats())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveVersion(w http.ResponseWriter, r *http.Request) {
|
func serveVersion(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,7 @@ func TestServeAdminMembers(t *testing.T) {
|
|||||||
cluster := &fakeCluster{
|
cluster := &fakeCluster{
|
||||||
members: map[uint64]*etcdserver.Member{1: &memb1, 2: &memb2},
|
members: map[uint64]*etcdserver.Member{1: &memb1, 2: &memb2},
|
||||||
}
|
}
|
||||||
h := &serverHandler{
|
h := &adminMembersHandler{
|
||||||
server: &serverRecorder{},
|
server: &serverRecorder{},
|
||||||
clock: clockwork.NewFakeClock(),
|
clock: clockwork.NewFakeClock(),
|
||||||
clusterInfo: cluster,
|
clusterInfo: cluster,
|
||||||
@ -588,7 +588,7 @@ func TestServeAdminMembers(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveAdminMembers(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
@ -616,13 +616,13 @@ func TestServeAdminMembersPut(t *testing.T) {
|
|||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
s := &serverRecorder{}
|
s := &serverRecorder{}
|
||||||
h := &serverHandler{
|
h := &adminMembersHandler{
|
||||||
server: s,
|
server: s,
|
||||||
clock: clockwork.NewFakeClock(),
|
clock: clockwork.NewFakeClock(),
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
|
|
||||||
h.serveAdminMembers(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
wcode := http.StatusCreated
|
wcode := http.StatusCreated
|
||||||
if rw.Code != wcode {
|
if rw.Code != wcode {
|
||||||
@ -658,12 +658,12 @@ func TestServeAdminMembersDelete(t *testing.T) {
|
|||||||
URL: mustNewURL(t, path.Join(adminMembersPrefix, "BEEF")),
|
URL: mustNewURL(t, path.Join(adminMembersPrefix, "BEEF")),
|
||||||
}
|
}
|
||||||
s := &serverRecorder{}
|
s := &serverRecorder{}
|
||||||
h := &serverHandler{
|
h := &adminMembersHandler{
|
||||||
server: s,
|
server: s,
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
|
|
||||||
h.serveAdminMembers(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
wcode := http.StatusNoContent
|
wcode := http.StatusNoContent
|
||||||
if rw.Code != wcode {
|
if rw.Code != wcode {
|
||||||
@ -767,12 +767,12 @@ func TestServeAdminMembersFail(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
h := &serverHandler{
|
h := &adminMembersHandler{
|
||||||
server: tt.server,
|
server: tt.server,
|
||||||
clock: clockwork.NewFakeClock(),
|
clock: clockwork.NewFakeClock(),
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveAdminMembers(rw, tt.req)
|
h.ServeHTTP(rw, tt.req)
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
}
|
}
|
||||||
@ -884,8 +884,8 @@ func TestServeMachines(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
h := &serverHandler{clusterInfo: cluster}
|
h := &deprecatedMachinesHandler{clusterInfo: cluster}
|
||||||
h.serveMachines(writer, req)
|
h.ServeHTTP(writer, req)
|
||||||
w := "http://localhost:8080, http://localhost:8081, http://localhost:8082"
|
w := "http://localhost:8080, http://localhost:8081, http://localhost:8082"
|
||||||
if g := writer.Body.String(); g != w {
|
if g := writer.Body.String(); g != w {
|
||||||
t.Errorf("body = %s, want %s", g, w)
|
t.Errorf("body = %s, want %s", g, w)
|
||||||
@ -907,11 +907,11 @@ func (ds *dummyStats) UpdateRecvApp(_ uint64, _ int64) {}
|
|||||||
func TestServeSelfStats(t *testing.T) {
|
func TestServeSelfStats(t *testing.T) {
|
||||||
wb := []byte("some statistics")
|
wb := []byte("some statistics")
|
||||||
w := string(wb)
|
w := string(wb)
|
||||||
sh := &serverHandler{
|
sh := &statsHandler{
|
||||||
stats: &dummyStats{data: wb},
|
stats: &dummyStats{data: wb},
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
sh.serveSelfStats(rw, &http.Request{Method: "GET"})
|
sh.serveSelf(rw, &http.Request{Method: "GET"})
|
||||||
if rw.Code != http.StatusOK {
|
if rw.Code != http.StatusOK {
|
||||||
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
||||||
}
|
}
|
||||||
@ -926,9 +926,9 @@ func TestServeSelfStats(t *testing.T) {
|
|||||||
|
|
||||||
func TestSelfServeStatsBad(t *testing.T) {
|
func TestSelfServeStatsBad(t *testing.T) {
|
||||||
for _, m := range []string{"PUT", "POST", "DELETE"} {
|
for _, m := range []string{"PUT", "POST", "DELETE"} {
|
||||||
sh := &serverHandler{}
|
sh := &statsHandler{}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
sh.serveSelfStats(
|
sh.serveSelf(
|
||||||
rw,
|
rw,
|
||||||
&http.Request{
|
&http.Request{
|
||||||
Method: m,
|
Method: m,
|
||||||
@ -942,9 +942,9 @@ func TestSelfServeStatsBad(t *testing.T) {
|
|||||||
|
|
||||||
func TestLeaderServeStatsBad(t *testing.T) {
|
func TestLeaderServeStatsBad(t *testing.T) {
|
||||||
for _, m := range []string{"PUT", "POST", "DELETE"} {
|
for _, m := range []string{"PUT", "POST", "DELETE"} {
|
||||||
sh := &serverHandler{}
|
sh := &statsHandler{}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
sh.serveLeaderStats(
|
sh.serveLeader(
|
||||||
rw,
|
rw,
|
||||||
&http.Request{
|
&http.Request{
|
||||||
Method: m,
|
Method: m,
|
||||||
@ -959,11 +959,11 @@ func TestLeaderServeStatsBad(t *testing.T) {
|
|||||||
func TestServeLeaderStats(t *testing.T) {
|
func TestServeLeaderStats(t *testing.T) {
|
||||||
wb := []byte("some statistics")
|
wb := []byte("some statistics")
|
||||||
w := string(wb)
|
w := string(wb)
|
||||||
sh := &serverHandler{
|
sh := &statsHandler{
|
||||||
stats: &dummyStats{data: wb},
|
stats: &dummyStats{data: wb},
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
sh.serveLeaderStats(rw, &http.Request{Method: "GET"})
|
sh.serveLeader(rw, &http.Request{Method: "GET"})
|
||||||
if rw.Code != http.StatusOK {
|
if rw.Code != http.StatusOK {
|
||||||
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
||||||
}
|
}
|
||||||
@ -979,11 +979,11 @@ func TestServeLeaderStats(t *testing.T) {
|
|||||||
func TestServeStoreStats(t *testing.T) {
|
func TestServeStoreStats(t *testing.T) {
|
||||||
wb := []byte("some statistics")
|
wb := []byte("some statistics")
|
||||||
w := string(wb)
|
w := string(wb)
|
||||||
sh := &serverHandler{
|
sh := &statsHandler{
|
||||||
stats: &dummyStats{data: wb},
|
stats: &dummyStats{data: wb},
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
sh.serveStoreStats(rw, &http.Request{Method: "GET"})
|
sh.serveStore(rw, &http.Request{Method: "GET"})
|
||||||
if rw.Code != http.StatusOK {
|
if rw.Code != http.StatusOK {
|
||||||
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
t.Errorf("code = %d, want %d", rw.Code, http.StatusOK)
|
||||||
}
|
}
|
||||||
@ -1002,9 +1002,8 @@ func TestServeVersion(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating request: %v", err)
|
t.Fatalf("error creating request: %v", err)
|
||||||
}
|
}
|
||||||
h := &serverHandler{}
|
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveVersion(rw, req)
|
serveVersion(rw, req)
|
||||||
if rw.Code != http.StatusOK {
|
if rw.Code != http.StatusOK {
|
||||||
t.Errorf("code=%d, want %d", rw.Code, http.StatusOK)
|
t.Errorf("code=%d, want %d", rw.Code, http.StatusOK)
|
||||||
}
|
}
|
||||||
@ -1022,9 +1021,8 @@ func TestServeVersionFails(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating request: %v", err)
|
t.Fatalf("error creating request: %v", err)
|
||||||
}
|
}
|
||||||
h := &serverHandler{}
|
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveVersion(rw, req)
|
serveVersion(rw, req)
|
||||||
if rw.Code != http.StatusMethodNotAllowed {
|
if rw.Code != http.StatusMethodNotAllowed {
|
||||||
t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed)
|
t.Errorf("method %s: code=%d, want %d", m, rw.Code, http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
@ -1102,12 +1100,12 @@ func TestBadServeKeys(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tt := range testBadCases {
|
for i, tt := range testBadCases {
|
||||||
h := &serverHandler{
|
h := &keysHandler{
|
||||||
timeout: 0, // context times out immediately
|
timeout: 0, // context times out immediately
|
||||||
server: tt.server,
|
server: tt.server,
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveKeys(rw, tt.req)
|
h.ServeHTTP(rw, tt.req)
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
}
|
}
|
||||||
@ -1127,14 +1125,14 @@ func TestServeKeysEvent(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
h := &serverHandler{
|
h := &keysHandler{
|
||||||
timeout: time.Hour,
|
timeout: time.Hour,
|
||||||
server: server,
|
server: server,
|
||||||
timer: &dummyRaftTimer{},
|
timer: &dummyRaftTimer{},
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
|
|
||||||
h.serveKeys(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
wcode := http.StatusOK
|
wcode := http.StatusOK
|
||||||
wbody := mustMarshalEvent(
|
wbody := mustMarshalEvent(
|
||||||
@ -1165,7 +1163,7 @@ func TestServeKeysWatch(t *testing.T) {
|
|||||||
Watcher: dw,
|
Watcher: dw,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
h := &serverHandler{
|
h := &keysHandler{
|
||||||
timeout: time.Hour,
|
timeout: time.Hour,
|
||||||
server: server,
|
server: server,
|
||||||
timer: &dummyRaftTimer{},
|
timer: &dummyRaftTimer{},
|
||||||
@ -1178,7 +1176,7 @@ func TestServeKeysWatch(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
|
|
||||||
h.serveKeys(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
wcode := http.StatusOK
|
wcode := http.StatusOK
|
||||||
wbody := mustMarshalEvent(
|
wbody := mustMarshalEvent(
|
||||||
|
@ -23,9 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
|
||||||
etcdErr "github.com/coreos/etcd/error"
|
etcdErr "github.com/coreos/etcd/error"
|
||||||
"github.com/coreos/etcd/etcdserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -38,16 +36,6 @@ const (
|
|||||||
|
|
||||||
var errClosed = errors.New("etcdhttp: client closed connection")
|
var errClosed = errors.New("etcdhttp: client closed connection")
|
||||||
|
|
||||||
// serverHandler provides http.Handlers for etcd client and raft communication.
|
|
||||||
type serverHandler struct {
|
|
||||||
timeout time.Duration
|
|
||||||
server etcdserver.Server
|
|
||||||
stats etcdserver.Stats
|
|
||||||
timer etcdserver.RaftTimer
|
|
||||||
clusterInfo etcdserver.ClusterInfo
|
|
||||||
clock clockwork.Clock
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeError logs and writes the given Error to the ResponseWriter
|
// writeError logs and writes the given Error to the ResponseWriter
|
||||||
// If Error is an etcdErr, it is rendered to the ResponseWriter
|
// If Error is an etcdErr, it is rendered to the ResponseWriter
|
||||||
// Otherwise, it is assumed to be an InternalServerError
|
// Otherwise, it is assumed to be an InternalServerError
|
||||||
|
@ -24,32 +24,41 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
"github.com/coreos/etcd/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||||
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/jonboulle/clockwork"
|
|
||||||
"github.com/coreos/etcd/etcdserver"
|
"github.com/coreos/etcd/etcdserver"
|
||||||
"github.com/coreos/etcd/raft/raftpb"
|
"github.com/coreos/etcd/raft/raftpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
raftPrefix = "/raft"
|
raftPrefix = "/raft"
|
||||||
membersPrefix = "/members"
|
peerMembersPrefix = "/members"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewPeerHandler generates an http.Handler to handle etcd peer (raft) requests.
|
// NewPeerHandler generates an http.Handler to handle etcd peer (raft) requests.
|
||||||
func NewPeerHandler(server *etcdserver.EtcdServer) http.Handler {
|
func NewPeerHandler(server *etcdserver.EtcdServer) http.Handler {
|
||||||
sh := &serverHandler{
|
rh := &raftHandler{
|
||||||
server: server,
|
|
||||||
stats: server,
|
stats: server,
|
||||||
|
server: server,
|
||||||
clusterInfo: server.Cluster,
|
clusterInfo: server.Cluster,
|
||||||
clock: clockwork.NewRealClock(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mh := &peerMembersHandler{
|
||||||
|
clusterInfo: server.Cluster,
|
||||||
|
}
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc(raftPrefix, sh.serveRaft)
|
|
||||||
mux.HandleFunc(membersPrefix, sh.serveMembers)
|
|
||||||
mux.HandleFunc("/", http.NotFound)
|
mux.HandleFunc("/", http.NotFound)
|
||||||
|
mux.Handle(raftPrefix, rh)
|
||||||
|
mux.Handle(peerMembersPrefix, mh)
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveRaft(w http.ResponseWriter, r *http.Request) {
|
type raftHandler struct {
|
||||||
|
stats etcdserver.Stats
|
||||||
|
server etcdserver.Server
|
||||||
|
clusterInfo etcdserver.ClusterInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *raftHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "POST") {
|
if !allowMethod(w, r.Method, "POST") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -92,14 +101,18 @@ func (h serverHandler) serveRaft(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h serverHandler) serveMembers(w http.ResponseWriter, r *http.Request) {
|
type peerMembersHandler struct {
|
||||||
|
clusterInfo etcdserver.ClusterInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *peerMembersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if !allowMethod(w, r.Method, "GET") {
|
if !allowMethod(w, r.Method, "GET") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cid := strconv.FormatUint(h.clusterInfo.ID(), 16)
|
cid := strconv.FormatUint(h.clusterInfo.ID(), 16)
|
||||||
w.Header().Set("X-Etcd-Cluster-ID", cid)
|
w.Header().Set("X-Etcd-Cluster-ID", cid)
|
||||||
|
|
||||||
if r.URL.Path != membersPrefix {
|
if r.URL.Path != peerMembersPrefix {
|
||||||
http.Error(w, "bad path", http.StatusBadRequest)
|
http.Error(w, "bad path", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coreos/etcd/etcdserver"
|
"github.com/coreos/etcd/etcdserver"
|
||||||
"github.com/coreos/etcd/raft/raftpb"
|
"github.com/coreos/etcd/raft/raftpb"
|
||||||
@ -169,13 +168,9 @@ func TestServeRaft(t *testing.T) {
|
|||||||
t.Fatalf("#%d: could not create request: %#v", i, err)
|
t.Fatalf("#%d: could not create request: %#v", i, err)
|
||||||
}
|
}
|
||||||
req.Header.Set("X-Etcd-Cluster-ID", tt.clusterID)
|
req.Header.Set("X-Etcd-Cluster-ID", tt.clusterID)
|
||||||
h := &serverHandler{
|
|
||||||
timeout: time.Hour,
|
|
||||||
server: &errServer{tt.serverErr},
|
|
||||||
clusterInfo: &fakeCluster{id: 0},
|
|
||||||
}
|
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveRaft(rw, req)
|
h := &raftHandler{stats: nil, server: &errServer{tt.serverErr}, clusterInfo: &fakeCluster{id: 0}}
|
||||||
|
h.ServeHTTP(rw, req)
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: got code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
}
|
}
|
||||||
@ -201,9 +196,9 @@ func TestServeMembersFails(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
h := &serverHandler{}
|
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveMembers(rw, &http.Request{Method: tt.method})
|
h := &peerMembersHandler{clusterInfo: nil}
|
||||||
|
h.ServeHTTP(rw, &http.Request{Method: tt.method})
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
}
|
}
|
||||||
@ -217,11 +212,7 @@ func TestServeMembersGet(t *testing.T) {
|
|||||||
id: 1,
|
id: 1,
|
||||||
members: map[uint64]*etcdserver.Member{1: &memb1, 2: &memb2},
|
members: map[uint64]*etcdserver.Member{1: &memb1, 2: &memb2},
|
||||||
}
|
}
|
||||||
h := &serverHandler{
|
h := &peerMembersHandler{clusterInfo: cluster}
|
||||||
server: &serverRecorder{},
|
|
||||||
clusterInfo: cluster,
|
|
||||||
}
|
|
||||||
|
|
||||||
msb, err := json.Marshal([]etcdserver.Member{memb1, memb2})
|
msb, err := json.Marshal([]etcdserver.Member{memb1, memb2})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -234,8 +225,8 @@ func TestServeMembersGet(t *testing.T) {
|
|||||||
wct string
|
wct string
|
||||||
wbody string
|
wbody string
|
||||||
}{
|
}{
|
||||||
{membersPrefix, http.StatusOK, "application/json", wms},
|
{peerMembersPrefix, http.StatusOK, "application/json", wms},
|
||||||
{path.Join(membersPrefix, "bad"), http.StatusBadRequest, "text/plain; charset=utf-8", "bad path\n"},
|
{path.Join(peerMembersPrefix, "bad"), http.StatusBadRequest, "text/plain; charset=utf-8", "bad path\n"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
@ -244,7 +235,7 @@ func TestServeMembersGet(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
rw := httptest.NewRecorder()
|
rw := httptest.NewRecorder()
|
||||||
h.serveMembers(rw, req)
|
h.ServeHTTP(rw, req)
|
||||||
|
|
||||||
if rw.Code != tt.wcode {
|
if rw.Code != tt.wcode {
|
||||||
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
t.Errorf("#%d: code=%d, want %d", i, rw.Code, tt.wcode)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user