Browse code

Fix #6231 - Accept chunked encoding on start

Docker-DCO-1.1-Signed-off-by: Brian Goff <cpuguy83@gmail.com> (github: cpuguy83)

Brian Goff authored on 2014/10/01 11:06:31
Showing 2 changed files
... ...
@@ -760,8 +760,13 @@ func postContainersStart(eng *engine.Engine, version version.Version, w http.Res
760 760
 		job  = eng.Job("start", name)
761 761
 	)
762 762
 
763
+	// If contentLength is -1, we can assumed chunked encoding
764
+	// or more technically that the length is unknown
765
+	// http://golang.org/src/pkg/net/http/request.go#L139
766
+	// net/http otherwise seems to swallow any headers related to chunked encoding
767
+	// including r.TransferEncoding
763 768
 	// allow a nil body for backwards compatibility
764
-	if r.Body != nil && r.ContentLength > 0 {
769
+	if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) {
765 770
 		if err := checkForJson(r); err != nil {
766 771
 			return err
767 772
 		}
... ...
@@ -1072,6 +1072,86 @@ func TestPostContainersCopyWhenContainerNotFound(t *testing.T) {
1072 1072
 	}
1073 1073
 }
1074 1074
 
1075
+// Regression test for https://github.com/docker/docker/issues/6231
1076
+func TestConstainersStartChunkedEncodingHostConfig(t *testing.T) {
1077
+	eng := NewTestEngine(t)
1078
+	defer mkDaemonFromEngine(eng, t).Nuke()
1079
+
1080
+	r := httptest.NewRecorder()
1081
+
1082
+	var testData engine.Env
1083
+	testData.Set("Image", "docker-test-image")
1084
+	testData.SetAuto("Volumes", map[string]struct{}{"/foo": {}})
1085
+	testData.Set("Cmd", "true")
1086
+	jsonData := bytes.NewBuffer(nil)
1087
+	if err := testData.Encode(jsonData); err != nil {
1088
+		t.Fatal(err)
1089
+	}
1090
+
1091
+	req, err := http.NewRequest("POST", "/containers/create?name=chunk_test", jsonData)
1092
+	if err != nil {
1093
+		t.Fatal(err)
1094
+	}
1095
+
1096
+	req.Header.Add("Content-Type", "application/json")
1097
+	if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
1098
+		t.Fatal(err)
1099
+	}
1100
+	assertHttpNotError(r, t)
1101
+
1102
+	var testData2 engine.Env
1103
+	testData2.SetAuto("Binds", []string{"/tmp:/foo"})
1104
+	jsonData = bytes.NewBuffer(nil)
1105
+	if err := testData2.Encode(jsonData); err != nil {
1106
+		t.Fatal(err)
1107
+	}
1108
+
1109
+	req, err = http.NewRequest("POST", "/containers/chunk_test/start", jsonData)
1110
+	if err != nil {
1111
+		t.Fatal(err)
1112
+	}
1113
+
1114
+	req.Header.Add("Content-Type", "application/json")
1115
+	// This is a cheat to make the http request do chunked encoding
1116
+	// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
1117
+	// http://golang.org/src/pkg/net/http/request.go?s=11980:12172
1118
+	req.ContentLength = -1
1119
+	if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
1120
+		t.Fatal(err)
1121
+	}
1122
+	assertHttpNotError(r, t)
1123
+
1124
+	type config struct {
1125
+		HostConfig struct {
1126
+			Binds []string
1127
+		}
1128
+	}
1129
+
1130
+	req, err = http.NewRequest("GET", "/containers/chunk_test/json", nil)
1131
+	if err != nil {
1132
+		t.Fatal(err)
1133
+	}
1134
+
1135
+	r2 := httptest.NewRecorder()
1136
+	req.Header.Add("Content-Type", "application/json")
1137
+	if err := server.ServeRequest(eng, api.APIVERSION, r2, req); err != nil {
1138
+		t.Fatal(err)
1139
+	}
1140
+	assertHttpNotError(r, t)
1141
+
1142
+	c := config{}
1143
+
1144
+	json.Unmarshal(r2.Body.Bytes(), &c)
1145
+
1146
+	if len(c.HostConfig.Binds) == 0 {
1147
+		t.Fatal("Chunked Encoding not handled")
1148
+	}
1149
+
1150
+	if c.HostConfig.Binds[0] != "/tmp:/foo" {
1151
+		t.Fatal("Chunked encoding not properly handled, execpted binds to be /tmp:/foo, got:", c.HostConfig.Binds[0])
1152
+	}
1153
+}
1154
+
1075 1155
 // Mocked types for tests
1076 1156
 type NopConn struct {
1077 1157
 	io.ReadCloser