]> Cypherpunks repositories - gostls13.git/commitdiff
net/url: add URL.Redacted to return a password scrubbed string
authornrxr <nrxrco@gmail.com>
Wed, 8 Apr 2020 10:21:40 +0000 (10:21 +0000)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Wed, 8 Apr 2020 21:04:32 +0000 (21:04 +0000)
Returning an URL.String() without the password is very useful for
situations where the URL is supposed to be logged and the password is
not useful to be shown.

This method re-uses URL.String() but with the password scrubbed and
substituted for a "xxxxx" in order to make it obvious that there was a
password. If the URL had no password then no "xxxxx" will be shown.

Fixes #34855

Change-Id: I7f17d81aa09a7963d2731d16fe15c6ae8e2285fc
GitHub-Last-Rev: 46d06dbc4f9e30a57667bb8d0627bc1abed83bdc
GitHub-Pull-Request: golang/go#35578
Reviewed-on: https://go-review.googlesource.com/c/go/+/207082
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
src/net/url/url.go
src/net/url/url_test.go

index 2880e820c308226d847b19926877f1f18f54a987..d811016f26ea1717ecfd857f0c59a4c7351135da 100644 (file)
@@ -821,6 +821,20 @@ func (u *URL) String() string {
        return buf.String()
 }
 
+// Redacted is like String but replaces any password with "xxxxx".
+// Only the password in u.URL is redacted.
+func (u *URL) Redacted() string {
+       if u == nil {
+               return ""
+       }
+
+       ru := *u
+       if _, has := ru.User.Password(); has {
+               ru.User = UserPassword(ru.User.Username(), "xxxxx")
+       }
+       return ru.String()
+}
+
 // Values maps a string key to a list of values.
 // It is typically used for query parameters and form values.
 // Unlike in the http.Header map, the keys in a Values map
index 79fd3d5c79f37f4d8ec1e19754e036c4f58f4721..c9f8a03f75360e45baf50d95b7ddb887b9d726e8 100644 (file)
@@ -765,6 +765,73 @@ func TestURLString(t *testing.T) {
        }
 }
 
+func TestURLRedacted(t *testing.T) {
+       cases := []struct {
+               name string
+               url  *URL
+               want string
+       }{
+               {
+                       name: "non-blank Password",
+                       url: &URL{
+                               Scheme: "http",
+                               Host:   "host.tld",
+                               Path:   "this:that",
+                               User:   UserPassword("user", "password"),
+                       },
+                       want: "http://user:xxxxx@host.tld/this:that",
+               },
+               {
+                       name: "blank Password",
+                       url: &URL{
+                               Scheme: "http",
+                               Host:   "host.tld",
+                               Path:   "this:that",
+                               User:   User("user"),
+                       },
+                       want: "http://user@host.tld/this:that",
+               },
+               {
+                       name: "nil User",
+                       url: &URL{
+                               Scheme: "http",
+                               Host:   "host.tld",
+                               Path:   "this:that",
+                               User:   UserPassword("", "password"),
+                       },
+                       want: "http://:xxxxx@host.tld/this:that",
+               },
+               {
+                       name: "blank Username, blank Password",
+                       url: &URL{
+                               Scheme: "http",
+                               Host:   "host.tld",
+                               Path:   "this:that",
+                       },
+                       want: "http://host.tld/this:that",
+               },
+               {
+                       name: "empty 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 := tt.url.Redacted(), tt.want; g != w {
+                               t.Fatalf("got: %q\nwant: %q", g, w)
+                       }
+               })
+       }
+}
+
 type EscapeTest struct {
        in  string
        out string