WriteWorkspaceOffline writes a HTML 400 error page for a workspace app. If appReq is not nil, it will be used to log the request details at debug level.
(log slog.Logger, accessURL *url.URL, rw http.ResponseWriter, r *http.Request, appReq *Request)
| 112 | // WriteWorkspaceOffline writes a HTML 400 error page for a workspace app. If |
| 113 | // appReq is not nil, it will be used to log the request details at debug level. |
| 114 | func WriteWorkspaceOffline(log slog.Logger, accessURL *url.URL, rw http.ResponseWriter, r *http.Request, appReq *Request) { |
| 115 | if appReq != nil { |
| 116 | slog.Helper() |
| 117 | log.Debug(r.Context(), |
| 118 | "workspace app unavailable: workspace stopped", |
| 119 | slog.F("username_or_id", appReq.UsernameOrID), |
| 120 | slog.F("workspace_and_agent", appReq.WorkspaceAndAgent), |
| 121 | slog.F("workspace_name_or_id", appReq.WorkspaceNameOrID), |
| 122 | slog.F("agent_name_or_id", appReq.AgentNameOrID), |
| 123 | slog.F("app_slug_or_port", appReq.AppSlugOrPort), |
| 124 | slog.F("hostname_prefix", appReq.Prefix), |
| 125 | ) |
| 126 | } |
| 127 | |
| 128 | actions := []site.Action{ |
| 129 | { |
| 130 | URL: accessURL.String(), |
| 131 | Text: "Back to site", |
| 132 | }, |
| 133 | } |
| 134 | |
| 135 | workspaceURL, err := url.Parse(accessURL.String()) |
| 136 | if err == nil { |
| 137 | workspaceURL.Path = path.Join(accessURL.Path, "@"+appReq.UsernameOrID, appReq.WorkspaceNameOrID) |
| 138 | actions = append(actions, site.Action{ |
| 139 | URL: workspaceURL.String(), |
| 140 | Text: "View workspace", |
| 141 | }) |
| 142 | } |
| 143 | |
| 144 | site.RenderStaticErrorPage(rw, r, site.ErrorPageData{ |
| 145 | Status: http.StatusBadRequest, |
| 146 | Title: "Workspace Offline", |
| 147 | Description: fmt.Sprintf("Last workspace transition was to the %q state. Start the workspace to access its applications.", codersdk.WorkspaceTransitionStop), |
| 148 | Actions: actions, |
| 149 | }) |
| 150 | } |