mirror of https://github.com/golang/go.git
http: parse query string always, not just in GET
Fixes #985. R=dsymonds, dsymonds1 CC=golang-dev https://golang.org/cl/1963044
This commit is contained in:
parent
8dc4c0b45f
commit
3bf656327e
|
|
@ -588,9 +588,22 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
|
|||
return req, nil
|
||||
}
|
||||
|
||||
// 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 map[string][]string, err os.Error) {
|
||||
m = make(map[string][]string)
|
||||
err = parseQuery(m, query)
|
||||
return
|
||||
}
|
||||
|
||||
func parseQuery(m map[string][]string, query string) (err os.Error) {
|
||||
for _, kv := range strings.Split(query, "&", -1) {
|
||||
if len(kv) == 0 {
|
||||
continue
|
||||
}
|
||||
kvPair := strings.Split(kv, "=", 2)
|
||||
|
||||
var key, value string
|
||||
|
|
@ -601,14 +614,13 @@ func ParseQuery(query string) (m map[string][]string, err os.Error) {
|
|||
}
|
||||
if e != nil {
|
||||
err = e
|
||||
continue
|
||||
}
|
||||
|
||||
vec := vector.StringVector(m[key])
|
||||
vec.Push(value)
|
||||
m[key] = vec
|
||||
}
|
||||
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// ParseForm parses the request body as a form for POST requests, or the raw query for GET requests.
|
||||
|
|
@ -618,32 +630,34 @@ func (r *Request) ParseForm() (err os.Error) {
|
|||
return
|
||||
}
|
||||
|
||||
var query string
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
query = r.URL.RawQuery
|
||||
case "POST":
|
||||
r.Form = make(map[string][]string)
|
||||
if r.URL != nil {
|
||||
err = parseQuery(r.Form, r.URL.RawQuery)
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
if r.Body == nil {
|
||||
r.Form = make(map[string][]string)
|
||||
return os.ErrorString("missing form body")
|
||||
}
|
||||
ct := r.Header["Content-Type"]
|
||||
switch strings.Split(ct, ";", 2)[0] {
|
||||
case "text/plain", "application/x-www-form-urlencoded", "":
|
||||
var b []byte
|
||||
if b, err = ioutil.ReadAll(r.Body); err != nil {
|
||||
r.Form = make(map[string][]string)
|
||||
return err
|
||||
b, e := ioutil.ReadAll(r.Body)
|
||||
if e != nil {
|
||||
if err == nil {
|
||||
err = e
|
||||
}
|
||||
break
|
||||
}
|
||||
e = parseQuery(r.Form, string(b))
|
||||
if err == nil {
|
||||
err = e
|
||||
}
|
||||
query = string(b)
|
||||
// TODO(dsymonds): Handle multipart/form-data
|
||||
default:
|
||||
r.Form = make(map[string][]string)
|
||||
return &badStringError{"unknown Content-Type", ct}
|
||||
}
|
||||
}
|
||||
r.Form, err = ParseQuery(query)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// FormValue returns the first value for the named component of the query.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ package http
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -68,6 +70,22 @@ func TestQuery(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPostQuery(t *testing.T) {
|
||||
req := &Request{Method: "POST"}
|
||||
req.URL, _ = ParseURL("http://www.google.com/search?q=foo&q=bar&both=x")
|
||||
req.Header = map[string]string{"Content-Type": "application/x-www-form-urlencoded; boo!"}
|
||||
req.Body = nopCloser{strings.NewReader("z=post&both=y")}
|
||||
if q := req.FormValue("q"); q != "foo" {
|
||||
t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
|
||||
}
|
||||
if z := req.FormValue("z"); z != "post" {
|
||||
t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
|
||||
}
|
||||
if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
|
||||
t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
|
||||
}
|
||||
}
|
||||
|
||||
type stringMap map[string]string
|
||||
type parseContentTypeTest struct {
|
||||
contentType stringMap
|
||||
|
|
|
|||
Loading…
Reference in New Issue