refactor: build application URL (#9601)

* refactor: build application URL

* fix
This commit is contained in:
Marcin Tojek
2023-09-08 14:01:57 +00:00
committed by GitHub
parent 392b11272b
commit ad23075e1b
6 changed files with 53 additions and 25 deletions
+3 -3
View File
@@ -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 <coder-vscode--<owner>-<workspace>-<agent?>>",
Use: "vscodessh <coder-vscode--<owner>--<workspace>--<agent?>>",
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--<owner>-<name>-<agent?>")
return xerrors.Errorf("invalid argument format. must be: coder-vscode--<owner>--<name>--<agent?>")
}
owner := parts[1]
name := parts[2]
+9 -1
View File
@@ -31,7 +31,15 @@ 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("--")
_, _ = 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
+8 -7
View File
@@ -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())
}
+16 -10
View File
@@ -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{
+8 -2
View File
@@ -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)
+9 -2
View File
@@ -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: