Skip to content

Commit

Permalink
cluster: add url
Browse files Browse the repository at this point in the history
  • Loading branch information
gernest committed Feb 25, 2024
1 parent 5b6ffd9 commit 4eba153
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 0 deletions.
67 changes: 67 additions & 0 deletions internal/cluster/http/url/url.go
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()
}
141 changes: 141 additions & 0 deletions internal/cluster/http/url/url_test.go
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)
}
}
}

0 comments on commit 4eba153

Please sign in to comment.