Commit 9f26170a authored by Rick Arnold's avatar Rick Arnold Committed by Brad Fitzpatrick

net/url: support query string without values

Previously, RawQuery was used to indicate the presence of a query
string in url.URL. However, this approach was not able to differentiate
between URLs that have no query string at all (http://foo.bar/) and
those that have a query with no values (http://foo.bar/?).

Add a ForceQuery field to indicate the latter form of URL and use it
in URL.String to create a matching URL with a trailing '?'.

Fixes #13488

Change-Id: Ifac663c73d35759bc6c33a00f84ab116b9b81684
Reviewed-on: https://go-review.googlesource.com/19931Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent bdc14698
......@@ -307,14 +307,15 @@ func escape(s string, mode encoding) string {
// construct a URL struct directly and set the Opaque field instead of Path.
// These still work as well.
type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path string
RawPath string // encoded path hint (Go 1.5 and later only; see EscapedPath method)
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path string
RawPath string // encoded path hint (Go 1.5 and later only; see EscapedPath method)
ForceQuery bool // append a query ('?') even if RawQuery is empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
}
// User returns a Userinfo containing the provided username
......@@ -459,7 +460,12 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
}
url.Scheme = strings.ToLower(url.Scheme)
rest, url.RawQuery = split(rest, "?", true)
if strings.HasSuffix(rest, "?") {
url.ForceQuery = true
rest = rest[:len(rest)-1]
} else {
rest, url.RawQuery = split(rest, "?", true)
}
if !strings.HasPrefix(rest, "/") {
if url.Scheme != "" {
......@@ -684,7 +690,7 @@ func (u *URL) String() string {
}
buf.WriteString(path)
}
if u.RawQuery != "" {
if u.ForceQuery || u.RawQuery != "" {
buf.WriteByte('?')
buf.WriteString(u.RawQuery)
}
......@@ -913,7 +919,7 @@ func (u *URL) RequestURI() string {
result = u.Scheme + ":" + result
}
}
if u.RawQuery != "" {
if u.ForceQuery || u.RawQuery != "" {
result += "?" + u.RawQuery
}
return result
......
......@@ -72,6 +72,17 @@ var urltests = []URLTest{
},
"ftp://john%20doe@www.google.com/",
},
// empty query
{
"http://www.google.com/?",
&URL{
Scheme: "http",
Host: "www.google.com",
Path: "/",
ForceQuery: true,
},
"",
},
// query
{
"http://www.google.com/?q=go+language",
......@@ -874,11 +885,13 @@ var resolveReferenceTests = []struct {
// Absolute URL references
{"http://foo.com?a=b", "https://bar.com/", "https://bar.com/"},
{"http://foo.com/", "https://bar.com/?a=b", "https://bar.com/?a=b"},
{"http://foo.com/", "https://bar.com/?", "https://bar.com/?"},
{"http://foo.com/bar", "mailto:foo@example.com", "mailto:foo@example.com"},
// Path-absolute references
{"http://foo.com/bar", "/baz", "http://foo.com/baz"},
{"http://foo.com/bar?a=b#f", "/baz", "http://foo.com/baz"},
{"http://foo.com/bar?a=b", "/baz?", "http://foo.com/baz?"},
{"http://foo.com/bar?a=b", "/baz?c=d", "http://foo.com/baz?c=d"},
// Scheme-relative
......@@ -1217,6 +1230,15 @@ var requritests = []RequestURITest{
},
"//foo",
},
{
&URL{
Scheme: "http",
Host: "example.com",
Path: "/foo",
ForceQuery: true,
},
"/foo?",
},
}
func TestRequestURI(t *testing.T) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment