readrequest_test.go 3.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"testing"
)

type reqTest struct {
16 17 18 19
	Raw   string
	Req   *Request
	Body  string
	Error string
20 21
}

22 23 24
var noError = ""
var noBody = ""

25 26
var reqTests = []reqTest{
	// Baseline test; All Request fields included for template use
Robert Griesemer's avatar
Robert Griesemer committed
27
	{
28 29 30 31 32 33 34 35 36 37 38 39
		"GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
			"Host: www.techcrunch.com\r\n" +
			"User-Agent: Fake\r\n" +
			"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
			"Accept-Language: en-us,en;q=0.5\r\n" +
			"Accept-Encoding: gzip,deflate\r\n" +
			"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
			"Keep-Alive: 300\r\n" +
			"Content-Length: 7\r\n" +
			"Proxy-Connection: keep-alive\r\n\r\n" +
			"abcdef\n???",

40
		&Request{
41 42 43
			Method: "GET",
			RawURL: "http://www.techcrunch.com/",
			URL: &URL{
44 45 46 47 48 49 50 51 52
				Raw:          "http://www.techcrunch.com/",
				Scheme:       "http",
				RawPath:      "/",
				RawAuthority: "www.techcrunch.com",
				RawUserinfo:  "",
				Host:         "www.techcrunch.com",
				Path:         "/",
				RawQuery:     "",
				Fragment:     "",
53
			},
54
			Proto:      "HTTP/1.1",
55 56
			ProtoMajor: 1,
			ProtoMinor: 1,
57 58 59 60 61 62 63 64
			Header: Header{
				"Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
				"Accept-Language":  {"en-us,en;q=0.5"},
				"Accept-Encoding":  {"gzip,deflate"},
				"Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
				"Keep-Alive":       {"300"},
				"Proxy-Connection": {"keep-alive"},
				"Content-Length":   {"7"},
65
				"User-Agent":       {"Fake"},
66
			},
67
			Close:         false,
68
			ContentLength: 7,
69
			Host:          "www.techcrunch.com",
70
			Form:          Values{},
71 72 73
		},

		"abcdef\n",
74 75

		noError,
76
	},
77

78 79 80 81 82
	// GET request with no body (the normal case)
	{
		"GET / HTTP/1.1\r\n" +
			"Host: foo.com\r\n\r\n",

83
		&Request{
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
			Method: "GET",
			RawURL: "/",
			URL: &URL{
				Raw:     "/",
				Path:    "/",
				RawPath: "/",
			},
			Proto:         "HTTP/1.1",
			ProtoMajor:    1,
			ProtoMinor:    1,
			Close:         false,
			ContentLength: 0,
			Host:          "foo.com",
			Form:          Values{},
		},

100 101
		noBody,
		noError,
102 103
	},

104 105 106 107 108 109
	// Tests that we don't parse a path that looks like a
	// scheme-relative URI as a scheme-relative URI.
	{
		"GET //user@host/is/actually/a/path/ HTTP/1.1\r\n" +
			"Host: test\r\n\r\n",

110
		&Request{
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
			Method: "GET",
			RawURL: "//user@host/is/actually/a/path/",
			URL: &URL{
				Raw:          "//user@host/is/actually/a/path/",
				Scheme:       "",
				RawPath:      "//user@host/is/actually/a/path/",
				RawAuthority: "",
				RawUserinfo:  "",
				Host:         "",
				Path:         "//user@host/is/actually/a/path/",
				RawQuery:     "",
				Fragment:     "",
			},
			Proto:         "HTTP/1.1",
			ProtoMajor:    1,
			ProtoMinor:    1,
127
			Header:        Header{},
128
			Close:         false,
129
			ContentLength: 0,
130
			Host:          "test",
131
			Form:          Values{},
132 133
		},

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
		noBody,
		noError,
	},

	// Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2)
	{
		"GET ../../../../etc/passwd HTTP/1.1\r\n" +
			"Host: test\r\n\r\n",
		nil,
		noBody,
		"parse ../../../../etc/passwd: invalid URI for request",
	},

	// Tests missing URL:
	{
		"GET  HTTP/1.1\r\n" +
			"Host: test\r\n\r\n",
		nil,
		noBody,
		"parse : empty url",
154
	},
155 156 157 158 159 160 161 162 163
}

func TestReadRequest(t *testing.T) {
	for i := range reqTests {
		tt := &reqTests[i]
		var braw bytes.Buffer
		braw.WriteString(tt.Raw)
		req, err := ReadRequest(bufio.NewReader(&braw))
		if err != nil {
164 165 166
			if err.String() != tt.Error {
				t.Errorf("#%d: error %q, want error %q", i, err.String(), tt.Error)
			}
167 168 169 170
			continue
		}
		rbody := req.Body
		req.Body = nil
171
		diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
172 173 174 175 176 177 178 179 180 181 182
		var bout bytes.Buffer
		if rbody != nil {
			io.Copy(&bout, rbody)
			rbody.Close()
		}
		body := bout.String()
		if body != tt.Body {
			t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
		}
	}
}