// license that can be found in the LICENSE file.
// Parse URLs (actually URIs, but that seems overly pedantic).
-// RFC 2396
+// RFC 3986
package http
type URL struct {
Raw string // the original string
Scheme string // scheme
- RawPath string // //[userinfo@]host/path[?query][#fragment]
Authority string // [userinfo@]host
Userinfo string // userinfo
Host string // host
+ RawPath string // /path[?query][#fragment]
Path string // /path
RawQuery string // query
Fragment string // fragment
if url.Scheme, path, err = getscheme(rawurl); err != nil {
goto Error
}
- url.RawPath = path
// RFC 2396: a relative URI (no scheme) has a ?query,
// but absolute URIs only have query if path begins with /
+ var query string
if url.Scheme == "" || len(path) > 0 && path[0] == '/' {
- path, url.RawQuery = split(path, '?', true)
+ path, query = split(path, '?', false)
+ if len(query) > 1 {
+ url.RawQuery = query[1:]
+ }
}
// Maybe path is //authority/path
if len(path) > 2 && path[0:2] == "//" {
url.Authority, path = split(path[2:], '/', false)
}
+ url.RawPath = path + query
// If there's no @, split's default is wrong. Check explicitly.
if strings.Index(url.Authority, "@") < 0 {
// ParseURLReference is like ParseURL but allows a trailing #fragment.
func ParseURLReference(rawurlref string) (url *URL, err os.Error) {
// Cut off #frag.
- rawurl, frag := split(rawurlref, '#', true)
+ rawurl, frag := split(rawurlref, '#', false)
if url, err = ParseURL(rawurl); err != nil {
return nil, err
}
- if url.Fragment, err = urlUnescape(frag, false); err != nil {
- return nil, &URLError{"parse", rawurl, err}
+ url.Raw += frag
+ url.RawPath += frag
+ if len(frag) > 1 {
+ frag = frag[1:]
+ if url.Fragment, err = urlUnescape(frag, false); err != nil {
+ return nil, &URLError{"parse", rawurl, err}
+ }
}
return url, nil
}
URLTest{
"http://www.google.com",
&URL{
- "http://www.google.com",
- "http", "//www.google.com",
- "www.google.com", "", "www.google.com",
- "", "", "",
+ Raw: "http://www.google.com",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
},
"",
},
URLTest{
"http://www.google.com/",
&URL{
- "http://www.google.com/",
- "http", "//www.google.com/",
- "www.google.com", "", "www.google.com",
- "/", "", "",
+ Raw: "http://www.google.com/",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/",
+ Path: "/",
},
"",
},
- // path with hex escaping... note that space roundtrips to +
+ // path with hex escaping
URLTest{
"http://www.google.com/file%20one%26two",
&URL{
- "http://www.google.com/file%20one%26two",
- "http", "//www.google.com/file%20one%26two",
- "www.google.com", "", "www.google.com",
- "/file one&two", "", "",
+ Raw: "http://www.google.com/file%20one%26two",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/file%20one%26two",
+ Path: "/file one&two",
},
"http://www.google.com/file%20one%26two",
},
URLTest{
"ftp://webmaster@www.google.com/",
&URL{
- "ftp://webmaster@www.google.com/",
- "ftp", "//webmaster@www.google.com/",
- "webmaster@www.google.com", "webmaster", "www.google.com",
- "/", "", "",
+ Raw: "ftp://webmaster@www.google.com/",
+ Scheme: "ftp",
+ Authority: "webmaster@www.google.com",
+ Userinfo: "webmaster",
+ Host: "www.google.com",
+ RawPath: "/",
+ Path: "/",
},
"",
},
URLTest{
"ftp://john%20doe@www.google.com/",
&URL{
- "ftp://john%20doe@www.google.com/",
- "ftp", "//john%20doe@www.google.com/",
- "john doe@www.google.com", "john doe", "www.google.com",
- "/", "", "",
+ Raw: "ftp://john%20doe@www.google.com/",
+ Scheme: "ftp",
+ Authority: "john doe@www.google.com",
+ Userinfo: "john doe",
+ Host: "www.google.com",
+ RawPath: "/",
+ Path: "/",
},
"ftp://john%20doe@www.google.com/",
},
URLTest{
"http://www.google.com/?q=go+language",
&URL{
- "http://www.google.com/?q=go+language",
- "http", "//www.google.com/?q=go+language",
- "www.google.com", "", "www.google.com",
- "/", "q=go+language", "",
+ Raw: "http://www.google.com/?q=go+language",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/?q=go+language",
+ Path: "/",
+ RawQuery: "q=go+language",
},
"",
},
URLTest{
"http://www.google.com/?q=go%20language",
&URL{
- "http://www.google.com/?q=go%20language",
- "http", "//www.google.com/?q=go%20language",
- "www.google.com", "", "www.google.com",
- "/", "q=go%20language", "",
+ Raw: "http://www.google.com/?q=go%20language",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/?q=go%20language",
+ Path: "/",
+ RawQuery: "q=go%20language",
},
"",
},
URLTest{
"http://www.google.com/a%20b?q=c+d",
&URL{
- "http://www.google.com/a%20b?q=c+d",
- "http", "//www.google.com/a%20b?q=c+d",
- "www.google.com", "", "www.google.com",
- "/a b", "q=c+d", "",
+ Raw: "http://www.google.com/a%20b?q=c+d",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/a%20b?q=c+d",
+ Path: "/a b",
+ RawQuery: "q=c+d",
},
"",
},
URLTest{
"http:www.google.com/?q=go+language",
&URL{
- "http:www.google.com/?q=go+language",
- "http", "www.google.com/?q=go+language",
- "", "", "",
- "www.google.com/?q=go+language", "", "",
+ Raw: "http:www.google.com/?q=go+language",
+ Scheme: "http",
+ RawPath: "www.google.com/?q=go+language",
+ Path: "www.google.com/?q=go+language",
},
"http:www.google.com/%3fq%3dgo%2blanguage",
},
URLTest{
"mailto:/webmaster@golang.org",
&URL{
- "mailto:/webmaster@golang.org",
- "mailto", "/webmaster@golang.org",
- "", "", "",
- "/webmaster@golang.org", "", "",
+ Raw: "mailto:/webmaster@golang.org",
+ Scheme: "mailto",
+ RawPath: "/webmaster@golang.org",
+ Path: "/webmaster@golang.org",
},
"",
},
URLTest{
"mailto:webmaster@golang.org",
&URL{
- "mailto:webmaster@golang.org",
- "mailto", "webmaster@golang.org",
- "", "", "",
- "webmaster@golang.org", "", "",
+ Raw: "mailto:webmaster@golang.org",
+ Scheme: "mailto",
+ RawPath: "webmaster@golang.org",
+ Path: "webmaster@golang.org",
},
"",
},
URLTest{
"/foo?query=http://bad",
&URL{
- "/foo?query=http://bad",
- "", "/foo?query=http://bad",
- "", "", "",
- "/foo", "query=http://bad", "",
+ Raw: "/foo?query=http://bad",
+ RawPath: "/foo?query=http://bad",
+ Path: "/foo",
+ RawQuery: "query=http://bad",
},
"",
},
URLTest{
"http://www.google.com/?q=go+language#foo",
&URL{
- "http://www.google.com/?q=go+language#foo",
- "http", "//www.google.com/?q=go+language#foo",
- "www.google.com", "", "www.google.com",
- "/", "q=go+language#foo", "",
+ Raw: "http://www.google.com/?q=go+language#foo",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/?q=go+language#foo",
+ Path: "/",
+ RawQuery: "q=go+language#foo",
},
"",
},
URLTest{
"http://www.google.com/?q=go+language#foo",
&URL{
- "http://www.google.com/?q=go+language",
- "http", "//www.google.com/?q=go+language",
- "www.google.com", "", "www.google.com",
- "/", "q=go+language", "foo",
+ Raw: "http://www.google.com/?q=go+language#foo",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/?q=go+language#foo",
+ Path: "/",
+ RawQuery: "q=go+language",
+ Fragment: "foo",
},
"",
},
URLTest{
"http://www.google.com/?q=go+language#foo%26bar",
&URL{
- "http://www.google.com/?q=go+language",
- "http", "//www.google.com/?q=go+language",
- "www.google.com", "", "www.google.com",
- "/", "q=go+language", "foo&bar",
+ Raw: "http://www.google.com/?q=go+language#foo%26bar",
+ Scheme: "http",
+ Authority: "www.google.com",
+ Host: "www.google.com",
+ RawPath: "/?q=go+language#foo%26bar",
+ Path: "/",
+ RawQuery: "q=go+language",
+ Fragment: "foo&bar",
},
"",
},