mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
chore: add workspace proxies to the backend (#7032)
Co-authored-by: Dean Sheather <dean@deansheather.com>
This commit is contained in:
@ -79,6 +79,10 @@ type Client struct {
|
||||
HTTPClient *http.Client
|
||||
URL *url.URL
|
||||
|
||||
// SessionTokenHeader is an optional custom header to use for setting tokens. By
|
||||
// default 'Coder-Session-Token' is used.
|
||||
SessionTokenHeader string
|
||||
|
||||
// Logger is optionally provided to log requests.
|
||||
// Method, URL, and response code will be logged by default.
|
||||
Logger slog.Logger
|
||||
@ -150,7 +154,12 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("create request: %w", err)
|
||||
}
|
||||
req.Header.Set(SessionTokenHeader, c.SessionToken())
|
||||
|
||||
tokenHeader := c.SessionTokenHeader
|
||||
if tokenHeader == "" {
|
||||
tokenHeader = SessionTokenHeader
|
||||
}
|
||||
req.Header.Set(tokenHeader, c.SessionToken())
|
||||
|
||||
if r != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
@ -1575,6 +1575,20 @@ type BuildInfoResponse struct {
|
||||
ExternalURL string `json:"external_url"`
|
||||
// Version returns the semantic version of the build.
|
||||
Version string `json:"version"`
|
||||
|
||||
// DashboardURL is the URL to hit the deployment's dashboard.
|
||||
// For external workspace proxies, this is the coderd they are connected
|
||||
// to.
|
||||
DashboardURL string `json:"dashboard_url"`
|
||||
|
||||
WorkspaceProxy bool `json:"workspace_proxy"`
|
||||
}
|
||||
|
||||
type WorkspaceProxyBuildInfo struct {
|
||||
// TODO: @emyrk what should we include here?
|
||||
WorkspaceProxy bool `json:"workspace_proxy"`
|
||||
// DashboardURL is the URL of the coderd this proxy is connected to.
|
||||
DashboardURL string `json:"dashboard_url"`
|
||||
}
|
||||
|
||||
// CanonicalVersion trims build information from the version.
|
||||
|
@ -200,18 +200,12 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parse url: %w", err)
|
||||
}
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("create cookie jar: %w", err)
|
||||
}
|
||||
jar.SetCookies(coordinateURL, []*http.Cookie{{
|
||||
Name: SessionTokenCookie,
|
||||
Value: c.SessionToken(),
|
||||
}})
|
||||
httpClient := &http.Client{
|
||||
Jar: jar,
|
||||
Transport: c.HTTPClient.Transport,
|
||||
coordinateHeaders := make(http.Header)
|
||||
tokenHeader := SessionTokenHeader
|
||||
if c.SessionTokenHeader != "" {
|
||||
tokenHeader = c.SessionTokenHeader
|
||||
}
|
||||
coordinateHeaders.Set(tokenHeader, c.SessionToken())
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@ -227,7 +221,8 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
|
||||
options.Logger.Debug(ctx, "connecting")
|
||||
// nolint:bodyclose
|
||||
ws, res, err := websocket.Dial(ctx, coordinateURL.String(), &websocket.DialOptions{
|
||||
HTTPClient: httpClient,
|
||||
HTTPClient: c.HTTPClient,
|
||||
HTTPHeader: coordinateHeaders,
|
||||
// Need to disable compression to avoid a data-race.
|
||||
CompressionMode: websocket.CompressionDisabled,
|
||||
})
|
||||
|
@ -11,19 +11,10 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CreateWorkspaceProxyRequest struct {
|
||||
Name string `json:"name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Icon string `json:"icon"`
|
||||
URL string `json:"url"`
|
||||
WildcardHostname string `json:"wildcard_hostname"`
|
||||
}
|
||||
|
||||
type WorkspaceProxy struct {
|
||||
ID uuid.UUID `db:"id" json:"id" format:"uuid"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id" format:"uuid"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Icon string `db:"icon" json:"icon"`
|
||||
ID uuid.UUID `db:"id" json:"id" format:"uuid"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Icon string `db:"icon" json:"icon"`
|
||||
// Full url including scheme of the proxy api url: https://us.example.com
|
||||
URL string `db:"url" json:"url"`
|
||||
// WildcardHostname with the wildcard for subdomain based app hosting: *.us.example.com
|
||||
@ -33,24 +24,37 @@ type WorkspaceProxy struct {
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateWorkspaceProxy(ctx context.Context, req CreateWorkspaceProxyRequest) (WorkspaceProxy, error) {
|
||||
type CreateWorkspaceProxyRequest struct {
|
||||
Name string `json:"name"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Icon string `json:"icon"`
|
||||
URL string `json:"url"`
|
||||
WildcardHostname string `json:"wildcard_hostname"`
|
||||
}
|
||||
|
||||
type CreateWorkspaceProxyResponse struct {
|
||||
Proxy WorkspaceProxy `json:"proxy"`
|
||||
ProxyToken string `json:"proxy_token"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateWorkspaceProxy(ctx context.Context, req CreateWorkspaceProxyRequest) (CreateWorkspaceProxyResponse, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost,
|
||||
"/api/v2/workspaceproxies",
|
||||
req,
|
||||
)
|
||||
if err != nil {
|
||||
return WorkspaceProxy{}, xerrors.Errorf("make request: %w", err)
|
||||
return CreateWorkspaceProxyResponse{}, xerrors.Errorf("make request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusCreated {
|
||||
return WorkspaceProxy{}, ReadBodyAsError(res)
|
||||
return CreateWorkspaceProxyResponse{}, ReadBodyAsError(res)
|
||||
}
|
||||
var resp WorkspaceProxy
|
||||
var resp CreateWorkspaceProxyResponse
|
||||
return resp, json.NewDecoder(res.Body).Decode(&resp)
|
||||
}
|
||||
|
||||
func (c *Client) WorkspaceProxiesByOrganization(ctx context.Context) ([]WorkspaceProxy, error) {
|
||||
func (c *Client) WorkspaceProxies(ctx context.Context) ([]WorkspaceProxy, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet,
|
||||
"/api/v2/workspaceproxies",
|
||||
nil,
|
||||
|
Reference in New Issue
Block a user