diff --git a/.circleci/config.yml b/.circleci/config.yml index 6d4f778d9..fa8463545 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -165,12 +165,12 @@ workflows: context: go-getter matrix: parameters: - go-version: ["1.15.13"] + go-version: ["1.15.13", "1.14.15"] name: linux-test-go-<< matrix.go-version >> - windows-tests: context: go-getter matrix: parameters: - go-version: ["1.15.13"] + go-version: ["1.15.13", "1.14.15"] gotestsum-version: ["0.4.1"] name: win-test-go-<< matrix.go-version >> diff --git a/client.go b/client.go index d531c2a77..5817d7384 100644 --- a/client.go +++ b/client.go @@ -298,7 +298,7 @@ func (c *Client) Get() error { // if we're specifying a subdir. err := g.Get(dst, u) if err != nil { - err = fmt.Errorf("error downloading '%s': %s", u.Redacted(), err) + err = fmt.Errorf("error downloading '%s': %s", RedactURL(u), err) return err } } diff --git a/url.go b/url.go new file mode 100644 index 000000000..1eaa4ce9f --- /dev/null +++ b/url.go @@ -0,0 +1,19 @@ +package getter + +import "net/url" + +// RedactURL is a port of url.Redacted from the standard library, +// which is like url.String but replaces any password with "xxxxx". +// Only the password in u.URL is redacted. This allows the library +// to maintain compatibility with go1.14. +func RedactURL(u *url.URL) string { + if u == nil { + return "" + } + + ru := *u + if _, has := ru.User.Password(); has { + ru.User = url.UserPassword(ru.User.Username(), "xxxxx") + } + return ru.String() +} diff --git a/url_test.go b/url_test.go new file mode 100644 index 000000000..3f87b0d7c --- /dev/null +++ b/url_test.go @@ -0,0 +1,73 @@ +package getter + +import ( + "net/url" + "testing" +) + +func TestRedactURL(t *testing.T) { + cases := []struct { + name string + url *url.URL + want string + }{ + { + name: "non-blank Password", + url: &url.URL{ + Scheme: "http", + Host: "host.tld", + Path: "this:that", + User: url.UserPassword("user", "password"), + }, + want: "http://user:xxxxx@host.tld/this:that", + }, + { + name: "blank Password", + url: &url.URL{ + Scheme: "http", + Host: "host.tld", + Path: "this:that", + User: url.User("user"), + }, + want: "http://user@host.tld/this:that", + }, + { + name: "nil User", + url: &url.URL{ + Scheme: "http", + Host: "host.tld", + Path: "this:that", + User: url.UserPassword("", "password"), + }, + want: "http://:xxxxx@host.tld/this:that", + }, + { + name: "blank Username, blank Password", + url: &url.URL{ + Scheme: "http", + Host: "host.tld", + Path: "this:that", + }, + want: "http://host.tld/this:that", + }, + { + name: "empty URL", + url: &url.URL{}, + want: "", + }, + { + name: "nil URL", + url: nil, + want: "", + }, + } + + for _, tt := range cases { + t := t + t.Run(tt.name, func(t *testing.T) { + if g, w := RedactURL(tt.url), tt.want; g != w { + t.Fatalf("got: %q\nwant: %q", g, w) + } + }) + } +}