Browse code

Fix line delimited JSON response

For GET /events, line delimit JSON.
Fixes #7047

Signed-off-by: Jessica Frazelle <jfrazelle@users.noreply.github.com>

Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jfrazelle@users.noreply.github.com> (github: )

Jessica Frazelle authored on 2014/09/05 04:02:52
Showing 3 changed files
... ...
@@ -278,6 +278,8 @@ func getEvents(eng *engine.Engine, version version.Version, w http.ResponseWrite
278 278
 	}
279 279
 
280 280
 	var job = eng.Job("events")
281
+	// lineDelimited JSON events was added #7047
282
+	job.SetenvBool("lineDelim", version.GreaterThanOrEqualTo("1.15"))
281 283
 	streamJSON(job, w, true)
282 284
 	job.Setenv("since", r.Form.Get("since"))
283 285
 	job.Setenv("until", r.Form.Get("until"))
... ...
@@ -101,6 +101,11 @@ func writeEvent(job *engine.Job, event *utils.JSONMessage) error {
101 101
 	// When sending an event JSON serialization errors are ignored, but all
102 102
 	// other errors lead to the eviction of the listener.
103 103
 	if b, err := json.Marshal(event); err == nil {
104
+
105
+		if job.GetenvBool("lineDelim") {
106
+			b = append(b, []byte("\r\n")...)
107
+		}
108
+
104 109
 		if _, err = job.Stdout.Write(b); err != nil {
105 110
 			return err
106 111
 		}
107 112
new file mode 100644
... ...
@@ -0,0 +1,57 @@
0
+package main
1
+
2
+import (
3
+	"bufio"
4
+	"bytes"
5
+	"encoding/json"
6
+	"fmt"
7
+	"testing"
8
+	"time"
9
+)
10
+
11
+func TestGetEventsLineDelim(t *testing.T) {
12
+	name := "testimageevents"
13
+	defer deleteImages(name)
14
+	_, err := buildImage(name,
15
+		`FROM scratch
16
+        MAINTAINER "docker"`,
17
+		true)
18
+	if err != nil {
19
+		t.Fatal(err)
20
+	}
21
+	if err := deleteImages(name); err != nil {
22
+		t.Fatal(err)
23
+	}
24
+
25
+	endpoint := fmt.Sprintf("/events?since=1&until=%d", time.Now().Unix())
26
+	body, err := sockRequest("GET", endpoint)
27
+	if err != nil {
28
+		t.Fatal(err)
29
+	}
30
+
31
+	linesRead := 0
32
+	scanner := bufio.NewScanner(bytes.NewReader(body))
33
+	for scanner.Scan() && linesRead < 2 {
34
+		line := scanner.Bytes()
35
+		if len(line) == 0 {
36
+			continue
37
+		}
38
+
39
+		// make sure line delimited json
40
+		res := make(map[string]interface{})
41
+		if err := json.Unmarshal(line, &res); err != nil {
42
+			t.Fatalf("Unmarshaling the line as JSON failed: %v", err)
43
+		}
44
+
45
+		linesRead++
46
+	}
47
+	if err := scanner.Err(); err != nil {
48
+		t.Fatalf("Scanner failed: %v", err)
49
+	}
50
+
51
+	if linesRead < 2 {
52
+		t.Fatalf("Only %d lines were read from the stream", linesRead)
53
+	}
54
+
55
+	logDone("events - test the api response is line delimited json")
56
+}