Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libgo / go / net / http / readrequest_test.go
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         "bufio"
9         "bytes"
10         "fmt"
11         "io"
12         "net/url"
13         "reflect"
14         "testing"
15 )
16
17 type reqTest struct {
18         Raw     string
19         Req     *Request
20         Body    string
21         Trailer Header
22         Error   string
23 }
24
25 var noError = ""
26 var noBody = ""
27 var noTrailer Header = nil
28
29 var reqTests = []reqTest{
30         // Baseline test; All Request fields included for template use
31         {
32                 "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
33                         "Host: www.techcrunch.com\r\n" +
34                         "User-Agent: Fake\r\n" +
35                         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
36                         "Accept-Language: en-us,en;q=0.5\r\n" +
37                         "Accept-Encoding: gzip,deflate\r\n" +
38                         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
39                         "Keep-Alive: 300\r\n" +
40                         "Content-Length: 7\r\n" +
41                         "Proxy-Connection: keep-alive\r\n\r\n" +
42                         "abcdef\n???",
43
44                 &Request{
45                         Method: "GET",
46                         URL: &url.URL{
47                                 Scheme: "http",
48                                 Host:   "www.techcrunch.com",
49                                 Path:   "/",
50                         },
51                         Proto:      "HTTP/1.1",
52                         ProtoMajor: 1,
53                         ProtoMinor: 1,
54                         Header: Header{
55                                 "Accept":           {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"},
56                                 "Accept-Language":  {"en-us,en;q=0.5"},
57                                 "Accept-Encoding":  {"gzip,deflate"},
58                                 "Accept-Charset":   {"ISO-8859-1,utf-8;q=0.7,*;q=0.7"},
59                                 "Keep-Alive":       {"300"},
60                                 "Proxy-Connection": {"keep-alive"},
61                                 "Content-Length":   {"7"},
62                                 "User-Agent":       {"Fake"},
63                         },
64                         Close:         false,
65                         ContentLength: 7,
66                         Host:          "www.techcrunch.com",
67                         RequestURI:    "http://www.techcrunch.com/",
68                 },
69
70                 "abcdef\n",
71
72                 noTrailer,
73                 noError,
74         },
75
76         // GET request with no body (the normal case)
77         {
78                 "GET / HTTP/1.1\r\n" +
79                         "Host: foo.com\r\n\r\n",
80
81                 &Request{
82                         Method: "GET",
83                         URL: &url.URL{
84                                 Path: "/",
85                         },
86                         Proto:         "HTTP/1.1",
87                         ProtoMajor:    1,
88                         ProtoMinor:    1,
89                         Header:        Header{},
90                         Close:         false,
91                         ContentLength: 0,
92                         Host:          "foo.com",
93                         RequestURI:    "/",
94                 },
95
96                 noBody,
97                 noTrailer,
98                 noError,
99         },
100
101         // Tests that we don't parse a path that looks like a
102         // scheme-relative URI as a scheme-relative URI.
103         {
104                 "GET //user@host/is/actually/a/path/ HTTP/1.1\r\n" +
105                         "Host: test\r\n\r\n",
106
107                 &Request{
108                         Method: "GET",
109                         URL: &url.URL{
110                                 Path: "//user@host/is/actually/a/path/",
111                         },
112                         Proto:         "HTTP/1.1",
113                         ProtoMajor:    1,
114                         ProtoMinor:    1,
115                         Header:        Header{},
116                         Close:         false,
117                         ContentLength: 0,
118                         Host:          "test",
119                         RequestURI:    "//user@host/is/actually/a/path/",
120                 },
121
122                 noBody,
123                 noTrailer,
124                 noError,
125         },
126
127         // Tests a bogus abs_path on the Request-Line (RFC 2616 section 5.1.2)
128         {
129                 "GET ../../../../etc/passwd HTTP/1.1\r\n" +
130                         "Host: test\r\n\r\n",
131                 nil,
132                 noBody,
133                 noTrailer,
134                 "parse ../../../../etc/passwd: invalid URI for request",
135         },
136
137         // Tests missing URL:
138         {
139                 "GET  HTTP/1.1\r\n" +
140                         "Host: test\r\n\r\n",
141                 nil,
142                 noBody,
143                 noTrailer,
144                 "parse : empty url",
145         },
146
147         // Tests chunked body with trailer:
148         {
149                 "POST / HTTP/1.1\r\n" +
150                         "Host: foo.com\r\n" +
151                         "Transfer-Encoding: chunked\r\n\r\n" +
152                         "3\r\nfoo\r\n" +
153                         "3\r\nbar\r\n" +
154                         "0\r\n" +
155                         "Trailer-Key: Trailer-Value\r\n" +
156                         "\r\n",
157                 &Request{
158                         Method: "POST",
159                         URL: &url.URL{
160                                 Path: "/",
161                         },
162                         TransferEncoding: []string{"chunked"},
163                         Proto:            "HTTP/1.1",
164                         ProtoMajor:       1,
165                         ProtoMinor:       1,
166                         Header:           Header{},
167                         ContentLength:    -1,
168                         Host:             "foo.com",
169                         RequestURI:       "/",
170                 },
171
172                 "foobar",
173                 Header{
174                         "Trailer-Key": {"Trailer-Value"},
175                 },
176                 noError,
177         },
178
179         // CONNECT request with domain name:
180         {
181                 "CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
182
183                 &Request{
184                         Method: "CONNECT",
185                         URL: &url.URL{
186                                 Host: "www.google.com:443",
187                         },
188                         Proto:         "HTTP/1.1",
189                         ProtoMajor:    1,
190                         ProtoMinor:    1,
191                         Header:        Header{},
192                         Close:         false,
193                         ContentLength: 0,
194                         Host:          "www.google.com:443",
195                         RequestURI:    "www.google.com:443",
196                 },
197
198                 noBody,
199                 noTrailer,
200                 noError,
201         },
202
203         // CONNECT request with IP address:
204         {
205                 "CONNECT 127.0.0.1:6060 HTTP/1.1\r\n\r\n",
206
207                 &Request{
208                         Method: "CONNECT",
209                         URL: &url.URL{
210                                 Host: "127.0.0.1:6060",
211                         },
212                         Proto:         "HTTP/1.1",
213                         ProtoMajor:    1,
214                         ProtoMinor:    1,
215                         Header:        Header{},
216                         Close:         false,
217                         ContentLength: 0,
218                         Host:          "127.0.0.1:6060",
219                         RequestURI:    "127.0.0.1:6060",
220                 },
221
222                 noBody,
223                 noTrailer,
224                 noError,
225         },
226
227         // CONNECT request for RPC:
228         {
229                 "CONNECT /_goRPC_ HTTP/1.1\r\n\r\n",
230
231                 &Request{
232                         Method: "CONNECT",
233                         URL: &url.URL{
234                                 Path: "/_goRPC_",
235                         },
236                         Proto:         "HTTP/1.1",
237                         ProtoMajor:    1,
238                         ProtoMinor:    1,
239                         Header:        Header{},
240                         Close:         false,
241                         ContentLength: 0,
242                         Host:          "",
243                         RequestURI:    "/_goRPC_",
244                 },
245
246                 noBody,
247                 noTrailer,
248                 noError,
249         },
250
251         // SSDP Notify request. golang.org/issue/3692
252         {
253                 "NOTIFY * HTTP/1.1\r\nServer: foo\r\n\r\n",
254                 &Request{
255                         Method: "NOTIFY",
256                         URL: &url.URL{
257                                 Path: "*",
258                         },
259                         Proto:      "HTTP/1.1",
260                         ProtoMajor: 1,
261                         ProtoMinor: 1,
262                         Header: Header{
263                                 "Server": []string{"foo"},
264                         },
265                         Close:         false,
266                         ContentLength: 0,
267                         RequestURI:    "*",
268                 },
269
270                 noBody,
271                 noTrailer,
272                 noError,
273         },
274
275         // OPTIONS request. Similar to golang.org/issue/3692
276         {
277                 "OPTIONS * HTTP/1.1\r\nServer: foo\r\n\r\n",
278                 &Request{
279                         Method: "OPTIONS",
280                         URL: &url.URL{
281                                 Path: "*",
282                         },
283                         Proto:      "HTTP/1.1",
284                         ProtoMajor: 1,
285                         ProtoMinor: 1,
286                         Header: Header{
287                                 "Server": []string{"foo"},
288                         },
289                         Close:         false,
290                         ContentLength: 0,
291                         RequestURI:    "*",
292                 },
293
294                 noBody,
295                 noTrailer,
296                 noError,
297         },
298 }
299
300 func TestReadRequest(t *testing.T) {
301         for i := range reqTests {
302                 tt := &reqTests[i]
303                 var braw bytes.Buffer
304                 braw.WriteString(tt.Raw)
305                 req, err := ReadRequest(bufio.NewReader(&braw))
306                 if err != nil {
307                         if err.Error() != tt.Error {
308                                 t.Errorf("#%d: error %q, want error %q", i, err.Error(), tt.Error)
309                         }
310                         continue
311                 }
312                 rbody := req.Body
313                 req.Body = nil
314                 diff(t, fmt.Sprintf("#%d Request", i), req, tt.Req)
315                 var bout bytes.Buffer
316                 if rbody != nil {
317                         _, err := io.Copy(&bout, rbody)
318                         if err != nil {
319                                 t.Fatalf("#%d. copying body: %v", i, err)
320                         }
321                         rbody.Close()
322                 }
323                 body := bout.String()
324                 if body != tt.Body {
325                         t.Errorf("#%d: Body = %q want %q", i, body, tt.Body)
326                 }
327                 if !reflect.DeepEqual(tt.Trailer, req.Trailer) {
328                         t.Errorf("#%d. Trailers differ.\n got: %v\nwant: %v", i, req.Trailer, tt.Trailer)
329                 }
330         }
331 }