-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
208 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package url | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
"strings" | ||
) | ||
|
||
var ( | ||
// ErrUserInfoExists is returned when a join address already contains | ||
// a username and a password. | ||
ErrUserInfoExists = errors.New("userinfo exists") | ||
) | ||
|
||
// NormalizeAddr ensures that the given URL has a HTTP protocol prefix. | ||
// If none is supplied, it prefixes the URL with "http://". | ||
func NormalizeAddr(addr string) string { | ||
if !strings.HasPrefix(addr, "http://") && !strings.HasPrefix(addr, "https://") { | ||
return fmt.Sprintf("http://%s", addr) | ||
} | ||
return addr | ||
} | ||
|
||
// EnsureHTTPS modifies the given URL, ensuring it is using the HTTPS protocol. | ||
func EnsureHTTPS(addr string) string { | ||
if !strings.HasPrefix(addr, "http://") && !strings.HasPrefix(addr, "https://") { | ||
return fmt.Sprintf("https://%s", addr) | ||
} | ||
return strings.Replace(addr, "http://", "https://", 1) | ||
} | ||
|
||
// CheckHTTPS returns true if the given URL uses HTTPS. | ||
func CheckHTTPS(addr string) bool { | ||
return strings.HasPrefix(addr, "https://") | ||
} | ||
|
||
// AddBasicAuth adds username and password to the join address. If username is empty | ||
// joinAddr is returned unchanged. If joinAddr already contains a username, ErrUserInfoExists | ||
// is returned. | ||
func AddBasicAuth(joinAddr, username, password string) (string, error) { | ||
if username == "" { | ||
return joinAddr, nil | ||
} | ||
|
||
u, err := url.Parse(joinAddr) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if u.User != nil && u.User.Username() != "" { | ||
return "", ErrUserInfoExists | ||
} | ||
|
||
u.User = url.UserPassword(username, password) | ||
return u.String(), nil | ||
} | ||
|
||
// RemoveBasicAuth returns a copy of the given URL, with any basic auth password | ||
// redacted. | ||
func RemoveBasicAuth(u string) string { | ||
uu, err := url.Parse(u) | ||
if err != nil { | ||
return u | ||
} | ||
return uu.Redacted() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package url | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func Test_NormalizeAddr(t *testing.T) { | ||
tests := []struct { | ||
orig string | ||
norm string | ||
}{ | ||
{ | ||
orig: "http://localhost:4001", | ||
norm: "http://localhost:4001", | ||
}, | ||
{ | ||
orig: "https://localhost:4001", | ||
norm: "https://localhost:4001", | ||
}, | ||
{ | ||
orig: "https://localhost:4001/foo", | ||
norm: "https://localhost:4001/foo", | ||
}, | ||
{ | ||
orig: "localhost:4001", | ||
norm: "http://localhost:4001", | ||
}, | ||
{ | ||
orig: "localhost", | ||
norm: "http://localhost", | ||
}, | ||
{ | ||
orig: ":4001", | ||
norm: "http://:4001", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
if NormalizeAddr(tt.orig) != tt.norm { | ||
t.Fatalf("%s not normalized correctly, got: %s", tt.orig, tt.norm) | ||
} | ||
} | ||
} | ||
|
||
func Test_EnsureHTTPS(t *testing.T) { | ||
tests := []struct { | ||
orig string | ||
ensured string | ||
}{ | ||
{ | ||
orig: "http://localhost:4001", | ||
ensured: "https://localhost:4001", | ||
}, | ||
{ | ||
orig: "https://localhost:4001", | ||
ensured: "https://localhost:4001", | ||
}, | ||
{ | ||
orig: "https://localhost:4001/foo", | ||
ensured: "https://localhost:4001/foo", | ||
}, | ||
{ | ||
orig: "localhost:4001", | ||
ensured: "https://localhost:4001", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
if e := EnsureHTTPS(tt.orig); e != tt.ensured { | ||
t.Fatalf("%s not HTTPS ensured correctly, exp %s, got %s", tt.orig, tt.ensured, e) | ||
} | ||
} | ||
} | ||
|
||
func Test_AddBasicAuth(t *testing.T) { | ||
var u string | ||
var err error | ||
|
||
u, err = AddBasicAuth("http://example.com", "user1", "pass1") | ||
if err != nil { | ||
t.Fatalf("failed to add user info: %s", err.Error()) | ||
} | ||
if exp, got := "http://user1:[email protected]", u; exp != got { | ||
t.Fatalf("wrong URL created, exp %s, got %s", exp, got) | ||
} | ||
|
||
u, err = AddBasicAuth("http://example.com", "user1", "") | ||
if err != nil { | ||
t.Fatalf("failed to add user info: %s", err.Error()) | ||
} | ||
if exp, got := "http://user1:@example.com", u; exp != got { | ||
t.Fatalf("wrong URL created, exp %s, got %s", exp, got) | ||
} | ||
|
||
u, err = AddBasicAuth("http://example.com", "", "pass1") | ||
if err != nil { | ||
t.Fatalf("failed to add user info: %s", err.Error()) | ||
} | ||
if exp, got := "http://example.com", u; exp != got { | ||
t.Fatalf("wrong URL created, exp %s, got %s", exp, got) | ||
} | ||
|
||
u, err = AddBasicAuth("http://user1:[email protected]", "user2", "pass2") | ||
if err == nil { | ||
t.Fatalf("failed to get expected error when UserInfo exists") | ||
} | ||
} | ||
|
||
func Test_RemoveBasicAuth(t *testing.T) { | ||
tests := []struct { | ||
orig string | ||
removed string | ||
}{ | ||
{ | ||
orig: "localhost", | ||
removed: "localhost", | ||
}, | ||
{ | ||
orig: "http://localhost:4001", | ||
removed: "http://localhost:4001", | ||
}, | ||
{ | ||
orig: "https://foo:bar@localhost", | ||
removed: "https://foo:xxxxx@localhost", | ||
}, | ||
{ | ||
orig: "https://foo:bar@localhost:4001", | ||
removed: "https://foo:xxxxx@localhost:4001", | ||
}, | ||
{ | ||
orig: "http://foo:bar@localhost:4001/path", | ||
removed: "http://foo:xxxxx@localhost:4001/path", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
if e := RemoveBasicAuth(tt.orig); e != tt.removed { | ||
t.Fatalf("%s BasicAuth not removed correctly, exp %s, got %s", tt.orig, tt.removed, e) | ||
} | ||
} | ||
} |