diff options
Diffstat (limited to 'src/pkg/http/request.go')
-rw-r--r-- | src/pkg/http/request.go | 126 |
1 files changed, 31 insertions, 95 deletions
diff --git a/src/pkg/http/request.go b/src/pkg/http/request.go index 2917cc1e6..ed41fa45c 100644 --- a/src/pkg/http/request.go +++ b/src/pkg/http/request.go @@ -12,7 +12,6 @@ import ( "bufio" "bytes" "crypto/tls" - "container/vector" "encoding/base64" "fmt" "io" @@ -23,6 +22,7 @@ import ( "os" "strconv" "strings" + "url" ) const ( @@ -73,9 +73,9 @@ var reqWriteExcludeHeader = map[string]bool{ // A Request represents a parsed HTTP request header. type Request struct { - Method string // GET, POST, PUT, etc. - RawURL string // The raw URL given in the request. - URL *URL // Parsed URL. + Method string // GET, POST, PUT, etc. + RawURL string // The raw URL given in the request. + URL *url.URL // Parsed URL. // The protocol version for incoming requests. // Outgoing requests always use HTTP/1.1. @@ -125,7 +125,7 @@ type Request struct { Host string // The parsed form. Only available after ParseForm is called. - Form Values + Form url.Values // The parsed multipart form, including file uploads. // Only available after ParseMultipartForm is called. @@ -290,22 +290,22 @@ func (req *Request) write(w io.Writer, usingProxy bool) os.Error { host = req.URL.Host } - uri := req.RawURL - if uri == "" { - uri = valueOrDefault(urlEscape(req.URL.Path, encodePath), "/") + urlStr := req.RawURL + if urlStr == "" { + urlStr = valueOrDefault(req.URL.EncodedPath(), "/") if req.URL.RawQuery != "" { - uri += "?" + req.URL.RawQuery + urlStr += "?" + req.URL.RawQuery } if usingProxy { - if uri == "" || uri[0] != '/' { - uri = "/" + uri + if urlStr == "" || urlStr[0] != '/' { + urlStr = "/" + urlStr } - uri = req.URL.Scheme + "://" + host + uri + urlStr = req.URL.Scheme + "://" + host + urlStr } } bw := bufio.NewWriter(w) - fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), uri) + fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr) // Header lines fmt.Fprintf(bw, "Host: %s\r\n", host) @@ -482,8 +482,8 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err os.Error) { } // NewRequest returns a new Request given a method, URL, and optional body. -func NewRequest(method, url string, body io.Reader) (*Request, os.Error) { - u, err := ParseURL(url) +func NewRequest(method, urlStr string, body io.Reader) (*Request, os.Error) { + u, err := url.Parse(urlStr) if err != nil { return nil, err } @@ -548,7 +548,7 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { return nil, &badStringError{"malformed HTTP version", req.Proto} } - if req.URL, err = ParseRequestURL(req.RawURL); err != nil { + if req.URL, err = url.ParseRequest(req.RawURL); err != nil { return nil, err } @@ -608,79 +608,6 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) { return req, nil } -// Values maps a string key to a list of values. -// It is typically used for query parameters and form values. -// Unlike in the Header map, the keys in a Values map -// are case-sensitive. -type Values map[string][]string - -// Get gets the first value associated with the given key. -// If there are no values associated with the key, Get returns -// the empty string. To access multiple values, use the map -// directly. -func (v Values) Get(key string) string { - if v == nil { - return "" - } - vs, ok := v[key] - if !ok || len(vs) == 0 { - return "" - } - return vs[0] -} - -// Set sets the key to value. It replaces any existing -// values. -func (v Values) Set(key, value string) { - v[key] = []string{value} -} - -// Add adds the key to value. It appends to any existing -// values associated with key. -func (v Values) Add(key, value string) { - v[key] = append(v[key], value) -} - -// Del deletes the values associated with key. -func (v Values) Del(key string) { - v[key] = nil, false -} - -// ParseQuery parses the URL-encoded query string and returns -// a map listing the values specified for each key. -// ParseQuery always returns a non-nil map containing all the -// valid query parameters found; err describes the first decoding error -// encountered, if any. -func ParseQuery(query string) (m Values, err os.Error) { - m = make(Values) - err = parseQuery(m, query) - return -} - -func parseQuery(m Values, query string) (err os.Error) { - for _, kv := range strings.Split(query, "&") { - if len(kv) == 0 { - continue - } - kvPair := strings.SplitN(kv, "=", 2) - - var key, value string - var e os.Error - key, e = URLUnescape(kvPair[0]) - if e == nil && len(kvPair) > 1 { - value, e = URLUnescape(kvPair[1]) - } - if e != nil { - err = e - continue - } - vec := vector.StringVector(m[key]) - vec.Push(value) - m[key] = vec - } - return err -} - // ParseForm parses the raw query. // For POST requests, it also parses the request body as a form. // ParseMultipartForm calls ParseForm automatically. @@ -690,9 +617,8 @@ func (r *Request) ParseForm() (err os.Error) { return } - r.Form = make(Values) if r.URL != nil { - err = parseQuery(r.Form, r.URL.RawQuery) + r.Form, err = url.ParseQuery(r.URL.RawQuery) } if r.Method == "POST" { if r.Body == nil { @@ -712,10 +638,20 @@ func (r *Request) ParseForm() (err os.Error) { if int64(len(b)) > maxFormSize { return os.NewError("http: POST too large") } - e = parseQuery(r.Form, string(b)) + var newValues url.Values + newValues, e = url.ParseQuery(string(b)) if err == nil { err = e } + if r.Form == nil { + r.Form = make(url.Values) + } + // Copy values into r.Form. TODO: make this smoother. + for k, vs := range newValues { + for _, value := range vs { + r.Form.Add(k, value) + } + } case "multipart/form-data": // handled by ParseMultipartForm default: @@ -732,6 +668,9 @@ func (r *Request) ParseForm() (err os.Error) { // ParseMultipartForm calls ParseForm if necessary. // After one call to ParseMultipartForm, subsequent calls have no effect. func (r *Request) ParseMultipartForm(maxMemory int64) os.Error { + if r.MultipartForm == multipartByReader { + return os.NewError("http: multipart handled by MultipartReader") + } if r.Form == nil { err := r.ParseForm() if err != nil { @@ -741,9 +680,6 @@ func (r *Request) ParseMultipartForm(maxMemory int64) os.Error { if r.MultipartForm != nil { return nil } - if r.MultipartForm == multipartByReader { - return os.NewError("http: multipart handled by MultipartReader") - } mr, err := r.multipartReader() if err == ErrNotMultipart { |