summaryrefslogtreecommitdiff
path: root/src/net/url
diff options
context:
space:
mode:
authorKale Blankenship <kale@lemnisys.com>2016-09-21 19:03:06 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2016-09-22 18:26:26 +0000
commitad5d91c17a3c0bc4acf9e4036b050517972432f0 (patch)
tree72b5c8bf28a674859b4adf5dae044b35a0fcd025 /src/net/url
parentcddddbc6231177c87b72f95209ab51abb74bcbc5 (diff)
downloadgo-git-ad5d91c17a3c0bc4acf9e4036b050517972432f0.tar.gz
net/url: prefix relative paths containing ":" in the first segment with "./"
This change modifies URL.String to prepend "./" to a relative URL which contains a colon in the first path segment. Per RFC 3986 §4.2: > A path segment that contains a colon character (e.g., "this:that") > cannot be used as the first segment of a relative-path reference, as > it would be mistaken for a scheme name. Such a segment must be > preceded by a dot-segment (e.g., "./this:that") to make a relative- > path reference. https://go-review.googlesource.com/27440 corrects the behavior for http.FileServer, but URL.String will still return an invalid URL. This CL reverts the changes to http.FileServer as they are unnecessary with this fix. Fixes #17184 Change-Id: I9211ae20f82c91b785d1b079b2cd766487d94225 Reviewed-on: https://go-review.googlesource.com/29610 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/net/url')
-rw-r--r--src/net/url/url.go11
-rw-r--r--src/net/url/url_test.go51
2 files changed, 53 insertions, 9 deletions
diff --git a/src/net/url/url.go b/src/net/url/url.go
index fb70dbac0d..d77e9295dd 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -713,6 +713,17 @@ func (u *URL) String() string {
if path != "" && path[0] != '/' && u.Host != "" {
buf.WriteByte('/')
}
+ if buf.Len() == 0 {
+ // RFC 3986 §4.2
+ // A path segment that contains a colon character (e.g., "this:that")
+ // cannot be used as the first segment of a relative-path reference, as
+ // it would be mistaken for a scheme name. Such a segment must be
+ // preceded by a dot-segment (e.g., "./this:that") to make a relative-
+ // path reference.
+ if i := strings.IndexByte(path, ':'); i > -1 && strings.IndexByte(path[:i], '/') == -1 {
+ buf.WriteString("./")
+ }
+ }
buf.WriteString(path)
}
if u.ForceQuery || u.RawQuery != "" {
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index a48da73e4a..6eac198448 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -676,6 +676,44 @@ func TestParseRequestURI(t *testing.T) {
}
}
+var stringURLTests = []struct {
+ url URL
+ want string
+}{
+ // No leading slash on path should prepend slash on String() call
+ {
+ url: URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "search",
+ },
+ want: "http://www.google.com/search",
+ },
+ // Relative path with first element containing ":" should be prepended with "./", golang.org/issue/17184
+ {
+ url: URL{
+ Path: "this:that",
+ },
+ want: "./this:that",
+ },
+ // Relative path with second element containing ":" should not be prepended with "./"
+ {
+ url: URL{
+ Path: "here/this:that",
+ },
+ want: "here/this:that",
+ },
+ // Non-relative path with first element containing ":" should not be prepended with "./"
+ {
+ url: URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "this:that",
+ },
+ want: "http://www.google.com/this:that",
+ },
+}
+
func TestURLString(t *testing.T) {
for _, tt := range urltests {
u, err := Parse(tt.in)
@@ -693,15 +731,10 @@ func TestURLString(t *testing.T) {
}
}
- // No leading slash on path should prepend
- // slash on String() call
- noslash := URL{
- Scheme: "http",
- Host: "www.google.com",
- Path: "search",
- }
- if got, want := noslash.String(), "http://www.google.com/search"; got != want {
- t.Errorf("No slash\ngot %q\nwant %q", got, want)
+ for _, tt := range stringURLTests {
+ if got := tt.url.String(); got != tt.want {
+ t.Errorf("%+v.String() = %q; want %q", tt.url, got, tt.want)
+ }
}
}