From 0ca04e8b1664d3bbb330e43be1ae01183810c1eb Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 8 Sep 2023 15:44:37 +0200 Subject: [PATCH 1/2] refactor: build application URL --- cli/vscodessh.go | 6 +++--- coderd/httpapi/url.go | 12 +++++++++++- coderd/workspaceagents.go | 15 ++++++++------- coderd/workspaceapps/apptest/setup.go | 26 ++++++++++++++++---------- coderd/workspaceapps/db_test.go | 10 ++++++++-- coderd/workspaceapps/request.go | 11 +++++++++-- 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/cli/vscodessh.go b/cli/vscodessh.go index 7e856df96983b..19a836214773f 100644 --- a/cli/vscodessh.go +++ b/cli/vscodessh.go @@ -40,9 +40,9 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd { cmd := &clibase.Cmd{ // A SSH config entry is added by the VS Code extension that // passes %h to ProxyCommand. The prefix of `coder-vscode--` - // is a magical string represented in our VS Cod extension. + // is a magical string represented in our VS Code extension. // It's not important here, only the delimiter `--` is. - Use: "vscodessh -->", + Use: "vscodessh ---->", Hidden: true, Middleware: clibase.RequireNArgs(1), Handler: func(inv *clibase.Invocation) error { @@ -93,7 +93,7 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd { parts := strings.Split(inv.Args[0], "--") if len(parts) < 3 { - return xerrors.Errorf("invalid argument format. must be: coder-vscode----") + return xerrors.Errorf("invalid argument format. must be: coder-vscode------") } owner := parts[1] name := parts[2] diff --git a/coderd/httpapi/url.go b/coderd/httpapi/url.go index d27abca5deaea..93ddbe7ff539e 100644 --- a/coderd/httpapi/url.go +++ b/coderd/httpapi/url.go @@ -31,7 +31,17 @@ type ApplicationURL struct { // String returns the application URL hostname without scheme. You will likely // want to append a period and the base hostname. func (a ApplicationURL) String() string { - return fmt.Sprintf("%s--%s--%s--%s", a.AppSlugOrPort, a.AgentName, a.WorkspaceName, a.Username) + var appURL strings.Builder + _, _ = appURL.WriteString(a.AppSlugOrPort) + _, _ = appURL.WriteString("--") + if a.AgentName != "" { + _, _ = appURL.WriteString(a.AgentName) + _, _ = appURL.WriteString("--") + } + _, _ = appURL.WriteString(a.WorkspaceName) + _, _ = appURL.WriteString("--") + _, _ = appURL.WriteString(a.Username) + return appURL.String() } // ParseSubdomainAppURL parses an ApplicationURL from the given subdomain. If diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index b7e69d718bde9..acff82c7f135d 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -151,13 +151,14 @@ func (api *API) workspaceAgentManifest(rw http.ResponseWriter, r *http.Request) return } - vscodeProxyURI := strings.ReplaceAll(api.AppHostname, "*", - fmt.Sprintf("%s://{{port}}--%s--%s--%s", - api.AccessURL.Scheme, - workspaceAgent.Name, - workspace.Name, - owner.Username, - )) + appHost := httpapi.ApplicationURL{ + AppSlugOrPort: "{{port}}", + AgentName: workspaceAgent.Name, + WorkspaceName: workspace.Name, + Username: owner.Username, + } + vscodeProxyURI := api.AccessURL.Scheme + "://" + strings.ReplaceAll(api.AppHostname, "*", appHost.String()) + if api.AccessURL.Port() != "" { vscodeProxyURI += fmt.Sprintf(":%s", api.AccessURL.Port()) } diff --git a/coderd/workspaceapps/apptest/setup.go b/coderd/workspaceapps/apptest/setup.go index 6ab541f078072..4dc8cd57eebca 100644 --- a/coderd/workspaceapps/apptest/setup.go +++ b/coderd/workspaceapps/apptest/setup.go @@ -21,6 +21,7 @@ import ( "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/agent" "github.com/coder/coder/v2/coderd/coderdtest" + "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/workspaceapps" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -141,10 +142,14 @@ func (d *Details) PathAppURL(app App) *url.URL { // SubdomainAppURL returns the URL for the given subdomain app. func (d *Details) SubdomainAppURL(app App) *url.URL { - host := fmt.Sprintf("%s--%s--%s--%s", app.AppSlugOrPort, app.AgentName, app.WorkspaceName, app.Username) - + appHost := httpapi.ApplicationURL{ + AppSlugOrPort: app.AppSlugOrPort, + AgentName: app.AgentName, + WorkspaceName: app.WorkspaceName, + Username: app.Username, + } u := *d.PathAppBaseURL - u.Host = strings.Replace(d.Options.AppHost, "*", host, 1) + u.Host = strings.Replace(d.Options.AppHost, "*", appHost.String(), 1) u.Path = "/" u.RawQuery = app.Query return &u @@ -355,13 +360,14 @@ func createWorkspaceWithApps(t *testing.T, client *codersdk.Client, orgID uuid.U if primaryAppHost.Host != "" { manifest, err := agentClient.Manifest(appHostCtx) require.NoError(t, err) - proxyURL := fmt.Sprintf( - "http://{{port}}--%s--%s--%s%s", - proxyTestAgentName, - workspace.Name, - me.Username, - strings.ReplaceAll(primaryAppHost.Host, "*", ""), - ) + + appHost := httpapi.ApplicationURL{ + AppSlugOrPort: "{{port}}", + AgentName: proxyTestAgentName, + WorkspaceName: workspace.Name, + Username: me.Username, + } + proxyURL := "http://" + appHost.String() + strings.ReplaceAll(primaryAppHost.Host, "*", "") require.Equal(t, proxyURL, manifest.VSCodePortProxyURI) } agentCloser := agent.New(agent.Options{ diff --git a/coderd/workspaceapps/db_test.go b/coderd/workspaceapps/db_test.go index 7f1b9c1d45339..3be987e28ca23 100644 --- a/coderd/workspaceapps/db_test.go +++ b/coderd/workspaceapps/db_test.go @@ -20,6 +20,7 @@ import ( "cdr.dev/slog/sloggers/slogtest" "github.com/coder/coder/v2/agent" "github.com/coder/coder/v2/coderd/coderdtest" + "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/workspaceapps" "github.com/coder/coder/v2/codersdk" @@ -760,8 +761,13 @@ func Test_ResolveRequest(t *testing.T) { redirectURI, err := url.Parse(redirectURIStr) require.NoError(t, err) - appHost := fmt.Sprintf("%s--%s--%s--%s", req.AppSlugOrPort, req.AgentNameOrID, req.WorkspaceNameOrID, req.UsernameOrID) - host := strings.Replace(api.AppHostname, "*", appHost, 1) + appHost := httpapi.ApplicationURL{ + AppSlugOrPort: req.AppSlugOrPort, + AgentName: req.AgentNameOrID, + WorkspaceName: req.WorkspaceNameOrID, + Username: req.UsernameOrID, + } + host := strings.Replace(api.AppHostname, "*", appHost.String(), 1) require.Equal(t, "http", redirectURI.Scheme) require.Equal(t, host, redirectURI.Host) diff --git a/coderd/workspaceapps/request.go b/coderd/workspaceapps/request.go index 949281d8020a6..88a84bfc063fb 100644 --- a/coderd/workspaceapps/request.go +++ b/coderd/workspaceapps/request.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/coder/coder/v2/coderd/database" + "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/codersdk" ) @@ -61,8 +62,14 @@ func (r IssueTokenRequest) AppBaseURL() (*url.URL, error) { if r.AppHostname == "" { return nil, xerrors.New("subdomain app hostname is required to generate subdomain app URL") } - appHost := fmt.Sprintf("%s--%s--%s--%s", r.AppRequest.AppSlugOrPort, r.AppRequest.AgentNameOrID, r.AppRequest.WorkspaceNameOrID, r.AppRequest.UsernameOrID) - u.Host = strings.Replace(r.AppHostname, "*", appHost, 1) + + appHost := httpapi.ApplicationURL{ + AppSlugOrPort: r.AppRequest.AppSlugOrPort, + AgentName: r.AppRequest.AgentNameOrID, + WorkspaceName: r.AppRequest.WorkspaceNameOrID, + Username: r.AppRequest.UsernameOrID, + } + u.Host = strings.Replace(r.AppHostname, "*", appHost.String(), 1) u.Path = r.AppRequest.BasePath return u, nil default: From a44ce801743b728f787da7cb399693b981b70d37 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Fri, 8 Sep 2023 15:46:29 +0200 Subject: [PATCH 2/2] fix --- coderd/httpapi/url.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/coderd/httpapi/url.go b/coderd/httpapi/url.go index 93ddbe7ff539e..b23d28bfd3990 100644 --- a/coderd/httpapi/url.go +++ b/coderd/httpapi/url.go @@ -34,10 +34,8 @@ func (a ApplicationURL) String() string { var appURL strings.Builder _, _ = appURL.WriteString(a.AppSlugOrPort) _, _ = appURL.WriteString("--") - if a.AgentName != "" { - _, _ = appURL.WriteString(a.AgentName) - _, _ = appURL.WriteString("--") - } + _, _ = appURL.WriteString(a.AgentName) + _, _ = appURL.WriteString("--") _, _ = appURL.WriteString(a.WorkspaceName) _, _ = appURL.WriteString("--") _, _ = appURL.WriteString(a.Username)