OSDN Git Service

Update to current version of Go library (revision 94d654be2064).
[pf3gnuchains/gcc-fork.git] / libgo / go / http / request.go
1 // Copyright 2009 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 // HTTP Request reading and parsing.
6
7 // The http package implements parsing of HTTP requests, replies,
8 // and URLs and provides an extensible HTTP server and a basic
9 // HTTP client.
10 package http
11
12 import (
13         "bufio"
14         "container/vector"
15         "fmt"
16         "io"
17         "io/ioutil"
18         "mime"
19         "mime/multipart"
20         "net/textproto"
21         "os"
22         "strconv"
23         "strings"
24 )
25
26 const (
27         maxLineLength  = 4096 // assumed <= bufio.defaultBufSize
28         maxValueLength = 4096
29         maxHeaderLines = 1024
30         chunkSize      = 4 << 10 // 4 KB chunks
31 )
32
33 // HTTP request parsing errors.
34 type ProtocolError struct {
35         os.ErrorString
36 }
37
38 var (
39         ErrLineTooLong          = &ProtocolError{"header line too long"}
40         ErrHeaderTooLong        = &ProtocolError{"header too long"}
41         ErrShortBody            = &ProtocolError{"entity body too short"}
42         ErrNotSupported         = &ProtocolError{"feature not supported"}
43         ErrUnexpectedTrailer    = &ProtocolError{"trailer header without chunked transfer encoding"}
44         ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
45         ErrNotMultipart         = &ProtocolError{"request Content-Type isn't multipart/form-data"}
46         ErrMissingBoundary      = &ProtocolError{"no multipart boundary param Content-Type"}
47 )
48
49 type badStringError struct {
50         what string
51         str  string
52 }
53
54 func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e.str) }
55
56 var reqExcludeHeader = map[string]bool{
57         "Host":              true,
58         "User-Agent":        true,
59         "Referer":           true,
60         "Content-Length":    true,
61         "Transfer-Encoding": true,
62         "Trailer":           true,
63 }
64
65 // A Request represents a parsed HTTP request header.
66 type Request struct {
67         Method     string // GET, POST, PUT, etc.
68         RawURL     string // The raw URL given in the request.
69         URL        *URL   // Parsed URL.
70         Proto      string // "HTTP/1.0"
71         ProtoMajor int    // 1
72         ProtoMinor int    // 0
73
74         // A header maps request lines to their values.
75         // If the header says
76         //
77         //      accept-encoding: gzip, deflate
78         //      Accept-Language: en-us
79         //      Connection: keep-alive
80         //
81         // then
82         //
83         //      Header = map[string]string{
84         //              "Accept-Encoding": "gzip, deflate",
85         //              "Accept-Language": "en-us",
86         //              "Connection": "keep-alive",
87         //      }
88         //
89         // HTTP defines that header names are case-insensitive.
90         // The request parser implements this by canonicalizing the
91         // name, making the first character and any characters
92         // following a hyphen uppercase and the rest lowercase.
93         Header Header
94
95         // The message body.
96         Body io.ReadCloser
97
98         // ContentLength records the length of the associated content.
99         // The value -1 indicates that the length is unknown.
100         // Values >= 0 indicate that the given number of bytes may be read from Body.
101         ContentLength int64
102
103         // TransferEncoding lists the transfer encodings from outermost to innermost.
104         // An empty list denotes the "identity" encoding.
105         TransferEncoding []string
106
107         // Whether to close the connection after replying to this request.
108         Close bool
109
110         // The host on which the URL is sought.
111         // Per RFC 2616, this is either the value of the Host: header
112         // or the host name given in the URL itself.
113         Host string
114
115         // The referring URL, if sent in the request.
116         //
117         // Referer is misspelled as in the request itself,
118         // a mistake from the earliest days of HTTP.
119         // This value can also be fetched from the Header map
120         // as Header["Referer"]; the benefit of making it
121         // available as a structure field is that the compiler
122         // can diagnose programs that use the alternate
123         // (correct English) spelling req.Referrer but cannot
124         // diagnose programs that use Header["Referrer"].
125         Referer string
126
127         // The User-Agent: header string, if sent in the request.
128         UserAgent string
129
130         // The parsed form. Only available after ParseForm is called.
131         Form map[string][]string
132
133         // Trailer maps trailer keys to values.  Like for Header, if the
134         // response has multiple trailer lines with the same key, they will be
135         // concatenated, delimited by commas.
136         Trailer Header
137 }
138
139 // ProtoAtLeast returns whether the HTTP protocol used
140 // in the request is at least major.minor.
141 func (r *Request) ProtoAtLeast(major, minor int) bool {
142         return r.ProtoMajor > major ||
143                 r.ProtoMajor == major && r.ProtoMinor >= minor
144 }
145
146 // MultipartReader returns a MIME multipart reader if this is a
147 // multipart/form-data POST request, else returns nil and an error.
148 func (r *Request) MultipartReader() (multipart.Reader, os.Error) {
149         v := r.Header.Get("Content-Type")
150         if v == "" {
151                 return nil, ErrNotMultipart
152         }
153         d, params := mime.ParseMediaType(v)
154         if d != "multipart/form-data" {
155                 return nil, ErrNotMultipart
156         }
157         boundary, ok := params["boundary"]
158         if !ok {
159                 return nil, ErrMissingBoundary
160         }
161         return multipart.NewReader(r.Body, boundary), nil
162 }
163
164 // Return value if nonempty, def otherwise.
165 func valueOrDefault(value, def string) string {
166         if value != "" {
167                 return value
168         }
169         return def
170 }
171
172 const defaultUserAgent = "Go http package"
173
174 // Write writes an HTTP/1.1 request -- header and body -- in wire format.
175 // This method consults the following fields of req:
176 //      Host
177 //      RawURL, if non-empty, or else URL
178 //      Method (defaults to "GET")
179 //      UserAgent (defaults to defaultUserAgent)
180 //      Referer
181 //      Header
182 //      Body
183 //
184 // If Body is present, Write forces "Transfer-Encoding: chunked" as a header
185 // and then closes Body when finished sending it.
186 func (req *Request) Write(w io.Writer) os.Error {
187         return req.write(w, false)
188 }
189
190 // WriteProxy is like Write but writes the request in the form
191 // expected by an HTTP proxy.  It includes the scheme and host
192 // name in the URI instead of using a separate Host: header line.
193 func (req *Request) WriteProxy(w io.Writer) os.Error {
194         return req.write(w, true)
195 }
196
197 func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
198         host := req.Host
199         if host == "" {
200                 host = req.URL.Host
201         }
202
203         uri := req.RawURL
204         if uri == "" {
205                 uri = valueOrDefault(urlEscape(req.URL.Path, encodePath), "/")
206                 if req.URL.RawQuery != "" {
207                         uri += "?" + req.URL.RawQuery
208                 }
209         }
210
211         if usingProxy {
212                 if uri == "" || uri[0] != '/' {
213                         uri = "/" + uri
214                 }
215                 uri = req.URL.Scheme + "://" + host + uri
216         }
217
218         fmt.Fprintf(w, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri)
219
220         // Header lines
221         if !usingProxy {
222                 fmt.Fprintf(w, "Host: %s\r\n", host)
223         }
224         fmt.Fprintf(w, "User-Agent: %s\r\n", valueOrDefault(req.UserAgent, defaultUserAgent))
225         if req.Referer != "" {
226                 fmt.Fprintf(w, "Referer: %s\r\n", req.Referer)
227         }
228
229         // Process Body,ContentLength,Close,Trailer
230         tw, err := newTransferWriter(req)
231         if err != nil {
232                 return err
233         }
234         err = tw.WriteHeader(w)
235         if err != nil {
236                 return err
237         }
238
239         // TODO: split long values?  (If so, should share code with Conn.Write)
240         // TODO: if Header includes values for Host, User-Agent, or Referer, this
241         // may conflict with the User-Agent or Referer headers we add manually.
242         // One solution would be to remove the Host, UserAgent, and Referer fields
243         // from Request, and introduce Request methods along the lines of
244         // Response.{GetHeader,AddHeader} and string constants for "Host",
245         // "User-Agent" and "Referer".
246         err = writeSortedKeyValue(w, req.Header, reqExcludeHeader)
247         if err != nil {
248                 return err
249         }
250
251         io.WriteString(w, "\r\n")
252
253         // Write body and trailer
254         err = tw.WriteBody(w)
255         if err != nil {
256                 return err
257         }
258
259         return nil
260 }
261
262 // Read a line of bytes (up to \n) from b.
263 // Give up if the line exceeds maxLineLength.
264 // The returned bytes are a pointer into storage in
265 // the bufio, so they are only valid until the next bufio read.
266 func readLineBytes(b *bufio.Reader) (p []byte, err os.Error) {
267         if p, err = b.ReadSlice('\n'); err != nil {
268                 // We always know when EOF is coming.
269                 // If the caller asked for a line, there should be a line.
270                 if err == os.EOF {
271                         err = io.ErrUnexpectedEOF
272                 } else if err == bufio.ErrBufferFull {
273                         err = ErrLineTooLong
274                 }
275                 return nil, err
276         }
277         if len(p) >= maxLineLength {
278                 return nil, ErrLineTooLong
279         }
280
281         // Chop off trailing white space.
282         var i int
283         for i = len(p); i > 0; i-- {
284                 if c := p[i-1]; c != ' ' && c != '\r' && c != '\t' && c != '\n' {
285                         break
286                 }
287         }
288         return p[0:i], nil
289 }
290
291 // readLineBytes, but convert the bytes into a string.
292 func readLine(b *bufio.Reader) (s string, err os.Error) {
293         p, e := readLineBytes(b)
294         if e != nil {
295                 return "", e
296         }
297         return string(p), nil
298 }
299
300 // Convert decimal at s[i:len(s)] to integer,
301 // returning value, string position where the digits stopped,
302 // and whether there was a valid number (digits, not too big).
303 func atoi(s string, i int) (n, i1 int, ok bool) {
304         const Big = 1000000
305         if i >= len(s) || s[i] < '0' || s[i] > '9' {
306                 return 0, 0, false
307         }
308         n = 0
309         for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
310                 n = n*10 + int(s[i]-'0')
311                 if n > Big {
312                         return 0, 0, false
313                 }
314         }
315         return n, i, true
316 }
317
318 // ParseHTTPVersion parses a HTTP version string.
319 // "HTTP/1.0" returns (1, 0, true).
320 func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
321         if len(vers) < 5 || vers[0:5] != "HTTP/" {
322                 return 0, 0, false
323         }
324         major, i, ok := atoi(vers, 5)
325         if !ok || i >= len(vers) || vers[i] != '.' {
326                 return 0, 0, false
327         }
328         minor, i, ok = atoi(vers, i+1)
329         if !ok || i != len(vers) {
330                 return 0, 0, false
331         }
332         return major, minor, true
333 }
334
335 type chunkedReader struct {
336         r   *bufio.Reader
337         n   uint64 // unread bytes in chunk
338         err os.Error
339 }
340
341 func newChunkedReader(r *bufio.Reader) *chunkedReader {
342         return &chunkedReader{r: r}
343 }
344
345 func (cr *chunkedReader) beginChunk() {
346         // chunk-size CRLF
347         var line string
348         line, cr.err = readLine(cr.r)
349         if cr.err != nil {
350                 return
351         }
352         cr.n, cr.err = strconv.Btoui64(line, 16)
353         if cr.err != nil {
354                 return
355         }
356         if cr.n == 0 {
357                 // trailer CRLF
358                 for {
359                         line, cr.err = readLine(cr.r)
360                         if cr.err != nil {
361                                 return
362                         }
363                         if line == "" {
364                                 break
365                         }
366                 }
367                 cr.err = os.EOF
368         }
369 }
370
371 func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) {
372         if cr.err != nil {
373                 return 0, cr.err
374         }
375         if cr.n == 0 {
376                 cr.beginChunk()
377                 if cr.err != nil {
378                         return 0, cr.err
379                 }
380         }
381         if uint64(len(b)) > cr.n {
382                 b = b[0:cr.n]
383         }
384         n, cr.err = cr.r.Read(b)
385         cr.n -= uint64(n)
386         if cr.n == 0 && cr.err == nil {
387                 // end of chunk (CRLF)
388                 b := make([]byte, 2)
389                 if _, cr.err = io.ReadFull(cr.r, b); cr.err == nil {
390                         if b[0] != '\r' || b[1] != '\n' {
391                                 cr.err = os.NewError("malformed chunked encoding")
392                         }
393                 }
394         }
395         return n, cr.err
396 }
397
398 // ReadRequest reads and parses a request from b.
399 func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
400
401         tp := textproto.NewReader(b)
402         req = new(Request)
403
404         // First line: GET /index.html HTTP/1.0
405         var s string
406         if s, err = tp.ReadLine(); err != nil {
407                 if err == os.EOF {
408                         err = io.ErrUnexpectedEOF
409                 }
410                 return nil, err
411         }
412
413         var f []string
414         if f = strings.Split(s, " ", 3); len(f) < 3 {
415                 return nil, &badStringError{"malformed HTTP request", s}
416         }
417         req.Method, req.RawURL, req.Proto = f[0], f[1], f[2]
418         var ok bool
419         if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
420                 return nil, &badStringError{"malformed HTTP version", req.Proto}
421         }
422
423         if req.URL, err = ParseRequestURL(req.RawURL); err != nil {
424                 return nil, err
425         }
426
427         // Subsequent lines: Key: value.
428         mimeHeader, err := tp.ReadMIMEHeader()
429         if err != nil {
430                 return nil, err
431         }
432         req.Header = Header(mimeHeader)
433
434         // RFC2616: Must treat
435         //      GET /index.html HTTP/1.1
436         //      Host: www.google.com
437         // and
438         //      GET http://www.google.com/index.html HTTP/1.1
439         //      Host: doesntmatter
440         // the same.  In the second case, any Host line is ignored.
441         req.Host = req.URL.Host
442         if req.Host == "" {
443                 req.Host = req.Header.Get("Host")
444         }
445         req.Header.Del("Host")
446
447         fixPragmaCacheControl(req.Header)
448
449         // Pull out useful fields as a convenience to clients.
450         req.Referer = req.Header.Get("Referer")
451         req.Header.Del("Referer")
452
453         req.UserAgent = req.Header.Get("User-Agent")
454         req.Header.Del("User-Agent")
455
456         // TODO: Parse specific header values:
457         //      Accept
458         //      Accept-Encoding
459         //      Accept-Language
460         //      Authorization
461         //      Cache-Control
462         //      Connection
463         //      Date
464         //      Expect
465         //      From
466         //      If-Match
467         //      If-Modified-Since
468         //      If-None-Match
469         //      If-Range
470         //      If-Unmodified-Since
471         //      Max-Forwards
472         //      Proxy-Authorization
473         //      Referer [sic]
474         //      TE (transfer-codings)
475         //      Trailer
476         //      Transfer-Encoding
477         //      Upgrade
478         //      User-Agent
479         //      Via
480         //      Warning
481
482         err = readTransfer(req, b)
483         if err != nil {
484                 return nil, err
485         }
486
487         return req, nil
488 }
489
490 // ParseQuery parses the URL-encoded query string and returns
491 // a map listing the values specified for each key.
492 // ParseQuery always returns a non-nil map containing all the
493 // valid query parameters found; err describes the first decoding error
494 // encountered, if any.
495 func ParseQuery(query string) (m map[string][]string, err os.Error) {
496         m = make(map[string][]string)
497         err = parseQuery(m, query)
498         return
499 }
500
501 func parseQuery(m map[string][]string, query string) (err os.Error) {
502         for _, kv := range strings.Split(query, "&", -1) {
503                 if len(kv) == 0 {
504                         continue
505                 }
506                 kvPair := strings.Split(kv, "=", 2)
507
508                 var key, value string
509                 var e os.Error
510                 key, e = URLUnescape(kvPair[0])
511                 if e == nil && len(kvPair) > 1 {
512                         value, e = URLUnescape(kvPair[1])
513                 }
514                 if e != nil {
515                         err = e
516                         continue
517                 }
518                 vec := vector.StringVector(m[key])
519                 vec.Push(value)
520                 m[key] = vec
521         }
522         return err
523 }
524
525 // ParseForm parses the request body as a form for POST requests, or the raw query for GET requests.
526 // It is idempotent.
527 func (r *Request) ParseForm() (err os.Error) {
528         if r.Form != nil {
529                 return
530         }
531
532         r.Form = make(map[string][]string)
533         if r.URL != nil {
534                 err = parseQuery(r.Form, r.URL.RawQuery)
535         }
536         if r.Method == "POST" {
537                 if r.Body == nil {
538                         return os.ErrorString("missing form body")
539                 }
540                 ct := r.Header.Get("Content-Type")
541                 switch strings.Split(ct, ";", 2)[0] {
542                 case "text/plain", "application/x-www-form-urlencoded", "":
543                         b, e := ioutil.ReadAll(r.Body)
544                         if e != nil {
545                                 if err == nil {
546                                         err = e
547                                 }
548                                 break
549                         }
550                         e = parseQuery(r.Form, string(b))
551                         if err == nil {
552                                 err = e
553                         }
554                 // TODO(dsymonds): Handle multipart/form-data
555                 default:
556                         return &badStringError{"unknown Content-Type", ct}
557                 }
558         }
559         return err
560 }
561
562 // FormValue returns the first value for the named component of the query.
563 // FormValue calls ParseForm if necessary.
564 func (r *Request) FormValue(key string) string {
565         if r.Form == nil {
566                 r.ParseForm()
567         }
568         if vs := r.Form[key]; len(vs) > 0 {
569                 return vs[0]
570         }
571         return ""
572 }
573
574 func (r *Request) expectsContinue() bool {
575         return strings.ToLower(r.Header.Get("Expect")) == "100-continue"
576 }
577
578 func (r *Request) wantsHttp10KeepAlive() bool {
579         if r.ProtoMajor != 1 || r.ProtoMinor != 0 {
580                 return false
581         }
582         return strings.Contains(strings.ToLower(r.Header.Get("Connection")), "keep-alive")
583 }