github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/pkg/net/http/responsewrite_test.go (about) 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 212 for i := range respWriteTests { 213 tt := &respWriteTests[i] 214 var braw bytes.Buffer 215 err := tt.Resp.Write(&braw) 216 if err != nil { 217 t.Errorf("error writing #%d: %s", i, err) 218 continue 219 } 220 sraw := braw.String() 221 if sraw != tt.Raw { 222 t.Errorf("Test %d, expecting:\n%q\nGot:\n%q\n", i, tt.Raw, sraw) 223 continue 224 } 225 } 226 }