Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab1af4f

Browse files
cstyanCallum Styan
authored andcommitted
fix(cli): request path-app traffic URL with trailing slash
The scaletest workspace-traffic app runs failed the WebSocket handshake because the constructed path-app URL lacked a trailing slash. coderd and workspace proxies 307-redirect /apps/<slug> to /apps/<slug>/, and the scaletest client rejects redirects, so the dial failed on all regions. A probe (exp scaletest workspace-traffic-probe) confirmed no-slash fails and slash succeeds across primary/europe/asia.
1 parent 7b876e2 commit ab1af4f

2 files changed

Lines changed: 86 additions & 1 deletion

File tree

cli/exp_scaletest_wstraffic.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,12 @@ func createWorkspaceAppConfig(client *codersdk.Client, appHost, app string, work
288288

289289
c.URL = fmt.Sprintf("%s://%s", client.URL.Scheme, strings.Replace(appHost, "*", agent.Apps[i].SubdomainName, 1))
290290
} else {
291-
c.URL = fmt.Sprintf("%s/@%s/%s.%s/apps/%s", client.URL.String(), workspace.OwnerName, workspace.Name, agent.Name, agent.Apps[i].Slug)
291+
// Path-based apps are served at a trailing-slash URL: coderd (and
292+
// workspace proxies) 307-redirect "/apps/<slug>" to "/apps/<slug>/"
293+
// (see coderd/workspaceapps/proxy.go). The scaletest client rejects
294+
// redirects, so the WebSocket handshake fails on the redirect unless we
295+
// request the already-normalized URL.
296+
c.URL = fmt.Sprintf("%s/@%s/%s.%s/apps/%s/", client.URL.String(), workspace.OwnerName, workspace.Name, agent.Name, agent.Apps[i].Slug)
292297
}
293298

294299
return c, nil
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//go:build !slim
2+
3+
package cli
4+
5+
import (
6+
"net/url"
7+
"testing"
8+
9+
"github.com/google/uuid"
10+
"github.com/stretchr/testify/require"
11+
12+
"github.com/coder/coder/v2/codersdk"
13+
)
14+
15+
func TestCreateWorkspaceAppConfig(t *testing.T) {
16+
t.Parallel()
17+
18+
newClient := func(t *testing.T, rawURL string) *codersdk.Client {
19+
t.Helper()
20+
u, err := url.Parse(rawURL)
21+
require.NoError(t, err)
22+
return codersdk.New(u)
23+
}
24+
25+
ws := codersdk.Workspace{
26+
ID: uuid.New(),
27+
Name: "myws",
28+
OwnerName: "alice",
29+
}
30+
31+
t.Run("Empty", func(t *testing.T) {
32+
t.Parallel()
33+
cfg, err := createWorkspaceAppConfig(newClient(t, "https://coder.example.com"), "", "", ws, codersdk.WorkspaceAgent{Name: "main"})
34+
require.NoError(t, err)
35+
require.Empty(t, cfg.Name)
36+
require.Empty(t, cfg.URL)
37+
})
38+
39+
t.Run("NotFound", func(t *testing.T) {
40+
t.Parallel()
41+
agent := codersdk.WorkspaceAgent{Name: "main"}
42+
_, err := createWorkspaceAppConfig(newClient(t, "https://coder.example.com"), "", "missing", ws, agent)
43+
require.Error(t, err)
44+
})
45+
46+
t.Run("PathAppHasTrailingSlash", func(t *testing.T) {
47+
t.Parallel()
48+
agent := codersdk.WorkspaceAgent{
49+
Name: "main",
50+
Apps: []codersdk.WorkspaceApp{{Slug: "wsec", Subdomain: false}},
51+
}
52+
cfg, err := createWorkspaceAppConfig(newClient(t, "https://coder.example.com"), "*.apps.example.com", "wsec", ws, agent)
53+
require.NoError(t, err)
54+
require.Equal(t, "wsec", cfg.Name)
55+
// The trailing slash avoids coderd's path-app normalization redirect,
56+
// which the scaletest client rejects.
57+
require.Equal(t, "https://coder.example.com/@alice/myws.main/apps/wsec/", cfg.URL)
58+
})
59+
60+
t.Run("SubdomainApp", func(t *testing.T) {
61+
t.Parallel()
62+
agent := codersdk.WorkspaceAgent{
63+
Name: "main",
64+
Apps: []codersdk.WorkspaceApp{{Slug: "wsec", Subdomain: true, SubdomainName: "wsec--main--myws--alice"}},
65+
}
66+
cfg, err := createWorkspaceAppConfig(newClient(t, "https://coder.example.com"), "*.apps.example.com", "wsec", ws, agent)
67+
require.NoError(t, err)
68+
require.Equal(t, "https://wsec--main--myws--alice.apps.example.com", cfg.URL)
69+
})
70+
71+
t.Run("SubdomainAppRequiresAppHost", func(t *testing.T) {
72+
t.Parallel()
73+
agent := codersdk.WorkspaceAgent{
74+
Name: "main",
75+
Apps: []codersdk.WorkspaceApp{{Slug: "wsec", Subdomain: true, SubdomainName: "wsec--main--myws--alice"}},
76+
}
77+
_, err := createWorkspaceAppConfig(newClient(t, "https://coder.example.com"), "", "wsec", ws, agent)
78+
require.Error(t, err)
79+
})
80+
}

0 commit comments

Comments
 (0)