Skip to content

Commit 686181e

Browse files
committed
url: handle ; in ParseQuery
Most web frameworks allow ; as a synonym for &, following a recommendation in some versions of the HTML specification. Do the same. Remove overuse of Split. Move ParseQuery tests from package http to package url. Fixes #2210. R=golang-dev, r CC=golang-dev https://golang.org/cl/4973062
1 parent 5ddf625 commit 686181e

File tree

3 files changed

+76
-67
lines changed

3 files changed

+76
-67
lines changed

src/pkg/http/request_test.go

-51
Original file line numberDiff line numberDiff line change
@@ -20,57 +20,6 @@ import (
2020
"url"
2121
)
2222

23-
type stringMultimap map[string][]string
24-
25-
type parseTest struct {
26-
query string
27-
out stringMultimap
28-
}
29-
30-
var parseTests = []parseTest{
31-
{
32-
query: "a=1&b=2",
33-
out: stringMultimap{"a": []string{"1"}, "b": []string{"2"}},
34-
},
35-
{
36-
query: "a=1&a=2&a=banana",
37-
out: stringMultimap{"a": []string{"1", "2", "banana"}},
38-
},
39-
{
40-
query: "ascii=%3Ckey%3A+0x90%3E",
41-
out: stringMultimap{"ascii": []string{"<key: 0x90>"}},
42-
},
43-
}
44-
45-
func TestParseForm(t *testing.T) {
46-
for i, test := range parseTests {
47-
form, err := url.ParseQuery(test.query)
48-
if err != nil {
49-
t.Errorf("test %d: Unexpected error: %v", i, err)
50-
continue
51-
}
52-
if len(form) != len(test.out) {
53-
t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
54-
}
55-
for k, evs := range test.out {
56-
vs, ok := form[k]
57-
if !ok {
58-
t.Errorf("test %d: Missing key %q", i, k)
59-
continue
60-
}
61-
if len(vs) != len(evs) {
62-
t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
63-
continue
64-
}
65-
for j, ev := range evs {
66-
if v := vs[j]; v != ev {
67-
t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
68-
}
69-
}
70-
}
71-
}
72-
}
73-
7423
func TestQuery(t *testing.T) {
7524
req := &Request{Method: "GET"}
7625
req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")

src/pkg/url/url.go

+19-11
Original file line numberDiff line numberDiff line change
@@ -532,20 +532,28 @@ func ParseQuery(query string) (m Values, err os.Error) {
532532
}
533533

534534
func parseQuery(m Values, query string) (err os.Error) {
535-
for _, kv := range strings.Split(query, "&") {
536-
if len(kv) == 0 {
535+
for query != "" {
536+
key := query
537+
if i := strings.IndexAny(key, "&;"); i >= 0 {
538+
key, query = key[:i], key[i+1:]
539+
} else {
540+
query = ""
541+
}
542+
if key == "" {
537543
continue
538544
}
539-
kvPair := strings.SplitN(kv, "=", 2)
540-
541-
var key, value string
542-
var e os.Error
543-
key, e = QueryUnescape(kvPair[0])
544-
if e == nil && len(kvPair) > 1 {
545-
value, e = QueryUnescape(kvPair[1])
545+
value := ""
546+
if i := strings.Index(key, "="); i >= 0 {
547+
key, value = key[:i], key[i+1:]
548+
}
549+
key, err1 := QueryUnescape(key)
550+
if err1 != nil {
551+
err = err1
552+
continue
546553
}
547-
if e != nil {
548-
err = e
554+
value, err1 = QueryUnescape(value)
555+
if err1 != nil {
556+
err = err1
549557
continue
550558
}
551559
m[key] = append(m[key], value)

src/pkg/url/url_test.go

+57-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ import (
1111
"testing"
1212
)
1313

14-
// TODO(rsc):
15-
// test Unescape
16-
// test Escape
17-
// test Parse
18-
1914
type URLTest struct {
2015
in string
2116
out *URL
@@ -696,3 +691,60 @@ func TestQueryValues(t *testing.T) {
696691
t.Errorf("second Get(bar) = %q, want %q", g, e)
697692
}
698693
}
694+
695+
type parseTest struct {
696+
query string
697+
out Values
698+
}
699+
700+
var parseTests = []parseTest{
701+
{
702+
query: "a=1&b=2",
703+
out: Values{"a": []string{"1"}, "b": []string{"2"}},
704+
},
705+
{
706+
query: "a=1&a=2&a=banana",
707+
out: Values{"a": []string{"1", "2", "banana"}},
708+
},
709+
{
710+
query: "ascii=%3Ckey%3A+0x90%3E",
711+
out: Values{"ascii": []string{"<key: 0x90>"}},
712+
},
713+
{
714+
query: "a=1;b=2",
715+
out: Values{"a": []string{"1"}, "b": []string{"2"}},
716+
},
717+
{
718+
query: "a=1&a=2;a=banana",
719+
out: Values{"a": []string{"1", "2", "banana"}},
720+
},
721+
}
722+
723+
func TestParseQuery(t *testing.T) {
724+
for i, test := range parseTests {
725+
form, err := ParseQuery(test.query)
726+
if err != nil {
727+
t.Errorf("test %d: Unexpected error: %v", i, err)
728+
continue
729+
}
730+
if len(form) != len(test.out) {
731+
t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
732+
}
733+
for k, evs := range test.out {
734+
vs, ok := form[k]
735+
if !ok {
736+
t.Errorf("test %d: Missing key %q", i, k)
737+
continue
738+
}
739+
if len(vs) != len(evs) {
740+
t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
741+
continue
742+
}
743+
for j, ev := range evs {
744+
if v := vs[j]; v != ev {
745+
t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
746+
}
747+
}
748+
}
749+
}
750+
}

0 commit comments

Comments
 (0)