netramesh

Форк
0
/
responsewrite_test.go 
291 строка · 6.9 Кб
1
// Copyright 2010 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
package http
6

7
import (
8
	"bytes"
9
	"io/ioutil"
10
	"strings"
11
	"testing"
12
)
13

14
type respWriteTest struct {
15
	Resp Response
16
	Raw  string
17
}
18

19
func TestResponseWrite(t *testing.T) {
20
	respWriteTests := []respWriteTest{
21
		// HTTP/1.0, identity coding; no trailer
22
		{
23
			Response{
24
				StatusCode:    503,
25
				ProtoMajor:    1,
26
				ProtoMinor:    0,
27
				Request:       dummyReq("GET"),
28
				Header:        Header{},
29
				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
30
				ContentLength: 6,
31
			},
32

33
			"HTTP/1.0 503 Service Unavailable\r\n" +
34
				"Content-Length: 6\r\n\r\n" +
35
				"abcdef",
36
		},
37
		// Unchunked response without Content-Length.
38
		{
39
			Response{
40
				StatusCode:    200,
41
				ProtoMajor:    1,
42
				ProtoMinor:    0,
43
				Request:       dummyReq("GET"),
44
				Header:        Header{},
45
				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
46
				ContentLength: -1,
47
			},
48
			"HTTP/1.0 200 OK\r\n" +
49
				"\r\n" +
50
				"abcdef",
51
		},
52
		// HTTP/1.1 response with unknown length and Connection: close
53
		{
54
			Response{
55
				StatusCode:    200,
56
				ProtoMajor:    1,
57
				ProtoMinor:    1,
58
				Request:       dummyReq("GET"),
59
				Header:        Header{},
60
				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
61
				ContentLength: -1,
62
				Close:         true,
63
			},
64
			"HTTP/1.1 200 OK\r\n" +
65
				"Connection: close\r\n" +
66
				"\r\n" +
67
				"abcdef",
68
		},
69
		// HTTP/1.1 response with unknown length and not setting connection: close
70
		{
71
			Response{
72
				StatusCode:    200,
73
				ProtoMajor:    1,
74
				ProtoMinor:    1,
75
				Request:       dummyReq11("GET"),
76
				Header:        Header{},
77
				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
78
				ContentLength: -1,
79
				Close:         false,
80
			},
81
			"HTTP/1.1 200 OK\r\n" +
82
				"Connection: close\r\n" +
83
				"\r\n" +
84
				"abcdef",
85
		},
86
		// HTTP/1.1 response with unknown length and not setting connection: close, but
87
		// setting chunked.
88
		{
89
			Response{
90
				StatusCode:       200,
91
				ProtoMajor:       1,
92
				ProtoMinor:       1,
93
				Request:          dummyReq11("GET"),
94
				Header:           Header{},
95
				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
96
				ContentLength:    -1,
97
				TransferEncoding: []string{"chunked"},
98
				Close:            false,
99
			},
100
			"HTTP/1.1 200 OK\r\n" +
101
				"Transfer-Encoding: chunked\r\n\r\n" +
102
				"6\r\nabcdef\r\n0\r\n\r\n",
103
		},
104
		// HTTP/1.1 response 0 content-length, and nil body
105
		{
106
			Response{
107
				StatusCode:    200,
108
				ProtoMajor:    1,
109
				ProtoMinor:    1,
110
				Request:       dummyReq11("GET"),
111
				Header:        Header{},
112
				Body:          nil,
113
				ContentLength: 0,
114
				Close:         false,
115
			},
116
			"HTTP/1.1 200 OK\r\n" +
117
				"Content-Length: 0\r\n" +
118
				"\r\n",
119
		},
120
		// HTTP/1.1 response 0 content-length, and non-nil empty body
121
		{
122
			Response{
123
				StatusCode:    200,
124
				ProtoMajor:    1,
125
				ProtoMinor:    1,
126
				Request:       dummyReq11("GET"),
127
				Header:        Header{},
128
				Body:          ioutil.NopCloser(strings.NewReader("")),
129
				ContentLength: 0,
130
				Close:         false,
131
			},
132
			"HTTP/1.1 200 OK\r\n" +
133
				"Content-Length: 0\r\n" +
134
				"\r\n",
135
		},
136
		// HTTP/1.1 response 0 content-length, and non-nil non-empty body
137
		{
138
			Response{
139
				StatusCode:    200,
140
				ProtoMajor:    1,
141
				ProtoMinor:    1,
142
				Request:       dummyReq11("GET"),
143
				Header:        Header{},
144
				Body:          ioutil.NopCloser(strings.NewReader("foo")),
145
				ContentLength: 0,
146
				Close:         false,
147
			},
148
			"HTTP/1.1 200 OK\r\n" +
149
				"Connection: close\r\n" +
150
				"\r\nfoo",
151
		},
152
		// HTTP/1.1, chunked coding; empty trailer; close
153
		{
154
			Response{
155
				StatusCode:       200,
156
				ProtoMajor:       1,
157
				ProtoMinor:       1,
158
				Request:          dummyReq("GET"),
159
				Header:           Header{},
160
				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
161
				ContentLength:    6,
162
				TransferEncoding: []string{"chunked"},
163
				Close:            true,
164
			},
165

166
			"HTTP/1.1 200 OK\r\n" +
167
				"Connection: close\r\n" +
168
				"Transfer-Encoding: chunked\r\n\r\n" +
169
				"6\r\nabcdef\r\n0\r\n\r\n",
170
		},
171

172
		// Header value with a newline character (Issue 914).
173
		// Also tests removal of leading and trailing whitespace.
174
		{
175
			Response{
176
				StatusCode: 204,
177
				ProtoMajor: 1,
178
				ProtoMinor: 1,
179
				Request:    dummyReq("GET"),
180
				Header: Header{
181
					"Foo": []string{" Bar\nBaz "},
182
				},
183
				Body:             nil,
184
				ContentLength:    0,
185
				TransferEncoding: []string{"chunked"},
186
				Close:            true,
187
			},
188

189
			"HTTP/1.1 204 No Content\r\n" +
190
				"Connection: close\r\n" +
191
				"Foo: Bar Baz\r\n" +
192
				"\r\n",
193
		},
194

195
		// Want a single Content-Length header. Fixing issue 8180 where
196
		// there were two.
197
		{
198
			Response{
199
				StatusCode:       StatusOK,
200
				ProtoMajor:       1,
201
				ProtoMinor:       1,
202
				Request:          &Request{Method: "POST"},
203
				Header:           Header{},
204
				ContentLength:    0,
205
				TransferEncoding: nil,
206
				Body:             nil,
207
			},
208
			"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n",
209
		},
210

211
		// When a response to a POST has Content-Length: -1, make sure we don't
212
		// write the Content-Length as -1.
213
		{
214
			Response{
215
				StatusCode:    StatusOK,
216
				ProtoMajor:    1,
217
				ProtoMinor:    1,
218
				Request:       &Request{Method: "POST"},
219
				Header:        Header{},
220
				ContentLength: -1,
221
				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
222
			},
223
			"HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nabcdef",
224
		},
225

226
		// Status code under 100 should be zero-padded to
227
		// three digits.  Still bogus, but less bogus. (be
228
		// consistent with generating three digits, since the
229
		// Transport requires it)
230
		{
231
			Response{
232
				StatusCode: 7,
233
				Status:     "license to violate specs",
234
				ProtoMajor: 1,
235
				ProtoMinor: 0,
236
				Request:    dummyReq("GET"),
237
				Header:     Header{},
238
				Body:       nil,
239
			},
240

241
			"HTTP/1.0 007 license to violate specs\r\nContent-Length: 0\r\n\r\n",
242
		},
243

244
		// No stutter.  Status code in 1xx range response should
245
		// not include a Content-Length header.  See issue #16942.
246
		{
247
			Response{
248
				StatusCode: 123,
249
				Status:     "123 Sesame Street",
250
				ProtoMajor: 1,
251
				ProtoMinor: 0,
252
				Request:    dummyReq("GET"),
253
				Header:     Header{},
254
				Body:       nil,
255
			},
256

257
			"HTTP/1.0 123 Sesame Street\r\n\r\n",
258
		},
259

260
		// Status code 204 (No content) response should not include a
261
		// Content-Length header.  See issue #16942.
262
		{
263
			Response{
264
				StatusCode: 204,
265
				Status:     "No Content",
266
				ProtoMajor: 1,
267
				ProtoMinor: 0,
268
				Request:    dummyReq("GET"),
269
				Header:     Header{},
270
				Body:       nil,
271
			},
272

273
			"HTTP/1.0 204 No Content\r\n\r\n",
274
		},
275
	}
276

277
	for i := range respWriteTests {
278
		tt := &respWriteTests[i]
279
		var braw bytes.Buffer
280
		err := tt.Resp.Write(&braw)
281
		if err != nil {
282
			t.Errorf("error writing #%d: %s", i, err)
283
			continue
284
		}
285
		sraw := braw.String()
286
		if sraw != tt.Raw {
287
			t.Errorf("Test %d, expecting:\n%q\nGot:\n%q\n", i, tt.Raw, sraw)
288
			continue
289
		}
290
	}
291
}
292

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.