diff --git a/app/router.go b/app/router.go index be8a8d37d..3d142f588 100644 --- a/app/router.go +++ b/app/router.go @@ -3,6 +3,7 @@ package main import ( "compress/gzip" "encoding/gob" + "encoding/json" "net/http" "net/url" "strings" @@ -87,7 +88,11 @@ func makeReportPostHandler(a Adder) http.HandlerFunc { } } - if err := gob.NewDecoder(reader).Decode(&rpt); err != nil { + decoder := gob.NewDecoder(reader).Decode + if strings.HasPrefix(r.Header.Get("Content-Type"), "application/json") { + decoder = json.NewDecoder(reader).Decode + } + if err := decoder(&rpt); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } diff --git a/app/router_test.go b/app/router_test.go index 11f10cd35..3bc4fc3e2 100644 --- a/app/router_test.go +++ b/app/router_test.go @@ -1,11 +1,19 @@ package main import ( + "bytes" + "encoding/gob" + "encoding/json" "net/http" + "net/http/httptest" "reflect" "testing" + "time" "github.com/gorilla/mux" + + "github.com/weaveworks/scope/test" + "github.com/weaveworks/scope/test/fixture" ) type v map[string]string @@ -28,3 +36,33 @@ func TestURLMatcher(t *testing.T) { test("/a/b/{c}", "/a/b/b", true, v{"c": "b"}) test("/a/b/{c}", "/a/b/b%2Fb", true, v{"c": "b/b"}) } + +func TestReportPostHandler(t *testing.T) { + test := func(contentType string, encoder func(interface{}) ([]byte, error)) { + b, err := encoder(fixture.Report) + if err != nil { + t.Fatalf("Content-Type %s: %s", contentType, err) + } + + r, _ := http.NewRequest("POST", "/api/report", bytes.NewReader(b)) + r.Header.Set("Content-Type", contentType) + w := httptest.NewRecorder() + c := NewCollector(1 * time.Minute) + makeReportPostHandler(c).ServeHTTP(w, r) + if w.Code != http.StatusOK { + t.Fatalf("Content-Type %s: http status: %d\nbody: %s", contentType, w.Code, w.Body.String()) + } + // Just check a few items, to confirm it parsed. Otherwise + // reflect.DeepEqual chokes on nil vs empty arrays. + if want, have := fixture.Report.Endpoint.Nodes, c.Report().Endpoint.Nodes; len(have) == 0 || len(want) != len(have) { + t.Fatalf("Content-Type %s: %v", contentType, test.Diff(have, want)) + } + } + + test("", func(v interface{}) ([]byte, error) { + buf := &bytes.Buffer{} + err := gob.NewEncoder(buf).Encode(v) + return buf.Bytes(), err + }) + test("application/json", json.Marshal) +}