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
}
}
+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