...

Source file src/net/http/responsewrite_test.go

Documentation: net/http

		 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"
		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:					io.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:					io.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:					io.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:					io.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:						 io.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:					io.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:					io.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:						 io.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:					io.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  

View as plain text