reconnectingPTYSignedToken issues a signed app token for use when connecting to the reconnecting PTY websocket on an external workspace proxy. This is set by the client as a query parameter when connecting. @Summary Issue signed app token for reconnecting PTY @ID issue-signed-app-token-for-reconnec
(rw http.ResponseWriter, r *http.Request)
| 869 | // @Router /api/v2/applications/reconnecting-pty-signed-token [post] |
| 870 | // @x-apidocgen {"skip": true} |
| 871 | func (api *API) reconnectingPTYSignedToken(rw http.ResponseWriter, r *http.Request) { |
| 872 | ctx := r.Context() |
| 873 | apiKey := httpmw.APIKey(r) |
| 874 | if !api.Authorize(r, policy.ActionCreate, apiKey) { |
| 875 | httpapi.ResourceNotFound(rw) |
| 876 | return |
| 877 | } |
| 878 | |
| 879 | var req codersdk.IssueReconnectingPTYSignedTokenRequest |
| 880 | if !httpapi.Read(ctx, rw, r, &req) { |
| 881 | return |
| 882 | } |
| 883 | |
| 884 | u, err := url.Parse(req.URL) |
| 885 | if err == nil && u.Scheme != "ws" && u.Scheme != "wss" { |
| 886 | err = xerrors.Errorf("invalid URL scheme %q, expected 'ws' or 'wss'", u.Scheme) |
| 887 | } |
| 888 | if err != nil { |
| 889 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 890 | Message: "Invalid URL.", |
| 891 | Detail: err.Error(), |
| 892 | }) |
| 893 | return |
| 894 | } |
| 895 | |
| 896 | // Assert the URL is a valid reconnecting-pty URL. |
| 897 | expectedPath := fmt.Sprintf("/api/v2/workspaceagents/%s/pty", req.AgentID.String()) |
| 898 | if u.Path != expectedPath { |
| 899 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 900 | Message: "Invalid URL path.", |
| 901 | Detail: "The provided URL is not a valid reconnecting PTY endpoint URL.", |
| 902 | }) |
| 903 | return |
| 904 | } |
| 905 | |
| 906 | scheme, err := api.AGPL.ValidWorkspaceAppHostname(ctx, u.Host, agpl.ValidWorkspaceAppHostnameOpts{ |
| 907 | // Only allow the proxy access URL as a hostname since we don't need a |
| 908 | // ticket for the primary dashboard URL terminal. |
| 909 | AllowPrimaryAccessURL: false, |
| 910 | AllowPrimaryWildcard: false, |
| 911 | AllowProxyAccessURL: true, |
| 912 | AllowProxyWildcard: false, |
| 913 | }) |
| 914 | if err != nil { |
| 915 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 916 | Message: "Failed to verify hostname in URL.", |
| 917 | Detail: err.Error(), |
| 918 | }) |
| 919 | return |
| 920 | } |
| 921 | if scheme == "" { |
| 922 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 923 | Message: "Invalid hostname in URL.", |
| 924 | Detail: "The hostname must be the primary wildcard app hostname, a workspace proxy access URL or a workspace proxy wildcard app hostname.", |
| 925 | }) |
| 926 | return |
| 927 | } |
| 928 |
nothing calls this directly
no test coverage detected