Skip to content

Commit aea235f

Browse files
committed
EPMDEDP-16652: fix: Normalize portal-url by trimming trailing slashes
Portal URLs with trailing slashes were breaking URL construction in multiple places, requiring scattered TrimSuffix calls to work around the issue. Normalize the PortalURL once in config.Resolve() by trimming trailing slashes, making it the single source of truth. Signed-off-by: Sergiy Kulanov <sergiy_kulanov@epam.com>
1 parent 5ef0242 commit aea235f

5 files changed

Lines changed: 47 additions & 5 deletions

File tree

internal/config/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func Resolve() (*Config, error) {
8181
return nil, fmt.Errorf("parsing config: %w", err)
8282
}
8383

84+
cfg.PortalURL = strings.TrimRight(cfg.PortalURL, "/")
8485
cfg.ConfigDir = configDir
8586
cfg.TokenPath = filepath.Join(configDir, "tokens.enc")
8687
cfg.KeyringService = "krci"
@@ -109,7 +110,7 @@ func Save(cfg *Config) error {
109110
existing.Set("client-id", cfg.ClientID)
110111
}
111112
if cfg.PortalURL != "" {
112-
existing.Set("portal-url", cfg.PortalURL)
113+
existing.Set("portal-url", strings.TrimRight(cfg.PortalURL, "/"))
113114
}
114115
if cfg.ClusterName != "" {
115116
existing.Set("cluster-name", cfg.ClusterName)

internal/config/config_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,48 @@ func TestSaveAndLoad(t *testing.T) {
6868
assert.Equal(t, cfg.PortalURL, viper.GetString("portal-url"))
6969
}
7070

71+
func TestResolveTrimsPortalURLTrailingSlashes(t *testing.T) {
72+
tests := []struct {
73+
name string
74+
input string
75+
want string
76+
}{
77+
{"no trailing slash", "https://portal.example.com", "https://portal.example.com"},
78+
{"single trailing slash", "https://portal.example.com/", "https://portal.example.com"},
79+
{"multiple trailing slashes", "https://portal.example.com///", "https://portal.example.com"},
80+
}
81+
for _, tt := range tests {
82+
t.Run(tt.name, func(t *testing.T) {
83+
viper.Reset()
84+
t.Setenv("KRCI_PORTAL_URL", tt.input)
85+
Init()
86+
87+
cfg, err := Resolve()
88+
require.NoError(t, err)
89+
90+
assert.Equal(t, tt.want, cfg.PortalURL)
91+
})
92+
}
93+
}
94+
95+
func TestSaveTrimsPortalURLTrailingSlash(t *testing.T) {
96+
dir := t.TempDir()
97+
98+
cfg := &Config{
99+
PortalURL: "https://portal.example.com/",
100+
ConfigDir: dir,
101+
}
102+
103+
require.NoError(t, Save(cfg))
104+
105+
configPath := filepath.Join(dir, "config.yaml")
106+
viper.Reset()
107+
viper.SetConfigFile(configPath)
108+
require.NoError(t, viper.ReadInConfig())
109+
110+
assert.Equal(t, "https://portal.example.com", viper.GetString("portal-url"))
111+
}
112+
71113
func TestSaveSkipsDefaults(t *testing.T) {
72114
dir := t.TempDir()
73115

internal/portal/config.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"io"
77
"net/http"
88
"net/url"
9-
"strings"
109
"time"
1110
)
1211

@@ -114,5 +113,5 @@ func validatePortalURL(portalURL string) error {
114113
}
115114

116115
func restURL(portalURL, path string) string {
117-
return strings.TrimSuffix(portalURL, "/") + "/rest" + path
116+
return portalURL + "/rest" + path
118117
}

internal/portal/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,5 @@ func TestRestURL(t *testing.T) {
180180
assert.Equal(t, "https://portal.example.com/rest/v1/config/oidc",
181181
restURL("https://portal.example.com", "/v1/config/oidc"))
182182
assert.Equal(t, "https://portal.example.com/rest/v1/config",
183-
restURL("https://portal.example.com/", "/v1/config"))
183+
restURL("https://portal.example.com", "/v1/config"))
184184
}

internal/portal/pipelinerun.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func NewPipelineRunService(
3030
) *PipelineRunService {
3131
return &PipelineRunService{
3232
client: client,
33-
portalURL: strings.TrimSuffix(portalURL, "/"),
33+
portalURL: portalURL,
3434
clusterName: clusterName,
3535
namespace: namespace,
3636
}

0 commit comments

Comments
 (0)