Skip to content

Commit 5db8392

Browse files
author
Varun Deep Saini
committed
Strip trailing slash from host in auth and configure commands
Signed-off-by: Varun Deep Saini <varun.23bcs10048@ms.sst.scaler.com>
1 parent 0c0b80f commit 5db8392

5 files changed

Lines changed: 76 additions & 20 deletions

File tree

cmd/auth/login.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ func setHostAndAccountId(ctx context.Context, existingProfile *profile.Profile,
303303
}
304304
}
305305

306+
authArguments.Host = strings.TrimSuffix(authArguments.Host, "/")
307+
306308
// Determine the host type and handle account ID / workspace ID accordingly
307309
cfg := &config.Config{
308310
Host: authArguments.Host,

cmd/auth/login_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,24 @@ func TestSetHost(t *testing.T) {
4949
assert.NoError(t, err)
5050
assert.Equal(t, "val from --host", authArguments.Host)
5151

52+
// Test setting host from flag with trailing slash is stripped
53+
authArguments.Host = "https://www.host1.com/"
54+
err = setHostAndAccountId(ctx, profile1, &authArguments, []string{})
55+
assert.NoError(t, err)
56+
assert.Equal(t, "https://www.host1.com", authArguments.Host)
57+
5258
// Test setting host from argument
5359
authArguments.Host = ""
5460
err = setHostAndAccountId(ctx, profile1, &authArguments, []string{"val from [HOST]"})
5561
assert.NoError(t, err)
5662
assert.Equal(t, "val from [HOST]", authArguments.Host)
5763

64+
// Test setting host from argument with trailing slash is stripped
65+
authArguments.Host = ""
66+
err = setHostAndAccountId(ctx, profile1, &authArguments, []string{"https://www.host1.com/"})
67+
assert.NoError(t, err)
68+
assert.Equal(t, "https://www.host1.com", authArguments.Host)
69+
5870
// Test setting host from profile
5971
authArguments.Host = ""
6072
err = setHostAndAccountId(ctx, profile1, &authArguments, []string{})

cmd/auth/token_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,22 @@ func TestToken_loadToken(t *testing.T) {
293293
},
294294
validateToken: validateToken,
295295
},
296+
{
297+
name: "host with trailing slash is stripped",
298+
args: loadTokenArgs{
299+
authArguments: &auth.AuthArguments{Host: "https://accounts.cloud.databricks.com/", AccountID: "active"},
300+
profileName: "",
301+
args: []string{},
302+
tokenTimeout: 1 * time.Hour,
303+
profiler: profiler,
304+
persistentAuthOpts: []u2m.PersistentAuthOption{
305+
u2m.WithTokenCache(tokenCache),
306+
u2m.WithOAuthEndpointSupplier(&MockApiClient{}),
307+
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshSuccessTokenResponse}}),
308+
},
309+
},
310+
validateToken: validateToken,
311+
},
296312
{
297313
name: "positional arg resolved as profile name",
298314
args: loadTokenArgs{
@@ -596,6 +612,26 @@ func TestToken_loadToken(t *testing.T) {
596612
},
597613
validateToken: validateToken,
598614
},
615+
{
616+
name: "no args, DATABRICKS_HOST env with trailing slash resolves",
617+
setupCtx: func(ctx context.Context) context.Context {
618+
ctx = env.Set(ctx, "DATABRICKS_HOST", "https://workspace-a.cloud.databricks.com/")
619+
return ctx
620+
},
621+
args: loadTokenArgs{
622+
authArguments: &auth.AuthArguments{},
623+
profileName: "",
624+
args: []string{},
625+
tokenTimeout: 1 * time.Hour,
626+
profiler: profiler,
627+
persistentAuthOpts: []u2m.PersistentAuthOption{
628+
u2m.WithTokenCache(tokenCache),
629+
u2m.WithOAuthEndpointSupplier(&MockApiClient{}),
630+
u2m.WithHttpClient(&http.Client{Transport: fixtures.SliceTransport{refreshSuccessTokenResponse}}),
631+
},
632+
},
633+
validateToken: validateToken,
634+
},
599635
{
600636
name: "no args, DATABRICKS_CONFIG_PROFILE env resolves",
601637
setupCtx: func(ctx context.Context) context.Context {

cmd/configure/host.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,27 @@ import (
66
"strings"
77
)
88

9-
// normalizeHost normalizes host input to prevent double https:// prefixes.
10-
// If the input already starts with https://, it returns it as-is.
11-
// If the input doesn't start with https://, it prepends https://.
9+
// normalizeHost ensures a https:// scheme is present and returns only scheme
10+
// and host, consistent with the normalizeHost in libs/databrickscfg/host.go.
1211
func normalizeHost(input string) string {
1312
input = strings.TrimSpace(input)
1413
u, err := url.Parse(input)
15-
// If the input is not a valid URL, return it as-is
1614
if err != nil {
1715
return input
1816
}
1917

20-
// If it already starts with https:// or http://, return as-is
21-
if u.Scheme == "https" || u.Scheme == "http" {
18+
if u.Scheme != "https" && u.Scheme != "http" {
19+
u, err = url.Parse("https://" + input)
20+
if err != nil {
21+
return input
22+
}
23+
}
24+
25+
if u.Host == "" {
2226
return input
2327
}
2428

25-
// Otherwise, prepend https://
26-
return "https://" + input
29+
return (&url.URL{Scheme: u.Scheme, Host: u.Host}).String()
2730
}
2831

2932
func validateHost(s string) error {
@@ -34,7 +37,7 @@ func validateHost(s string) error {
3437
if u.Host == "" || u.Scheme != "https" {
3538
return errors.New("must start with https://")
3639
}
37-
if u.Path != "" && u.Path != "/" {
40+
if u.Path != "" {
3841
return errors.New("must use empty path")
3942
}
4043
return nil

cmd/configure/host_test.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,30 @@ func TestNormalizeHost(t *testing.T) {
1212
expected string
1313
}{
1414
// Empty input
15-
{"", "https://"},
16-
{" ", "https://"},
15+
{"", ""},
16+
{" ", ""},
1717

1818
// Already has https://
1919
{"https://example.databricks.com", "https://example.databricks.com"},
20-
{"HTTPS://EXAMPLE.DATABRICKS.COM", "HTTPS://EXAMPLE.DATABRICKS.COM"},
21-
{"https://example.databricks.com/", "https://example.databricks.com/"},
20+
{"https://example.databricks.com/", "https://example.databricks.com"},
2221

2322
// Missing protocol (should add https://)
2423
{"example.databricks.com", "https://example.databricks.com"},
2524
{" example.databricks.com ", "https://example.databricks.com"},
2625
{"subdomain.example.databricks.com", "https://subdomain.example.databricks.com"},
26+
{"example.databricks.com/", "https://example.databricks.com"},
27+
28+
// Paths, query strings, and anchors are stripped
29+
{"https://example.databricks.com/path", "https://example.databricks.com"},
30+
{"https://example.databricks.com/path/", "https://example.databricks.com"},
31+
{"https://example.databricks.com?query", "https://example.databricks.com"},
32+
{"https://example.databricks.com#anchor", "https://example.databricks.com"},
2733

2834
// Edge cases
2935
{"https://", "https://"},
3036
{"example.com", "https://example.com"},
31-
{"https://example.databricks.com/path", "https://example.databricks.com/path"},
32-
{"https://example.databricks.com/path/", "https://example.databricks.com/path/"},
3337
{"http://localhost:8080", "http://localhost:8080"},
38+
{"http://localhost:8080/", "http://localhost:8080"},
3439
}
3540

3641
for _, test := range tests {
@@ -50,15 +55,13 @@ func TestValidateHost(t *testing.T) {
5055
err = validateHost("http://host")
5156
assert.ErrorContains(t, err, "must start with https://")
5257
err = validateHost("ftp://host")
58+
assert.ErrorContains(t, err, "must start with https://")
5359

5460
// Must use empty path
55-
assert.ErrorContains(t, err, "must start with https://")
5661
err = validateHost("https://host/path")
5762
assert.ErrorContains(t, err, "must use empty path")
5863

59-
// Ignore query params
60-
err = validateHost("https://host/?query")
61-
assert.NoError(t, err)
62-
err = validateHost("https://host/")
64+
// Valid hosts
65+
err = validateHost("https://host")
6366
assert.NoError(t, err)
6467
}

0 commit comments

Comments
 (0)