@Summary User-scoped tailnet RPC connection @ID user-scoped-tailnet-rpc-connection @Security CoderSessionToken @Tags Agents @Success 101 @Router /api/v2/tailnet [get]
(rw http.ResponseWriter, r *http.Request)
| 2240 | // @Success 101 |
| 2241 | // @Router /api/v2/tailnet [get] |
| 2242 | func (api *API) tailnetRPCConn(rw http.ResponseWriter, r *http.Request) { |
| 2243 | ctx := r.Context() |
| 2244 | |
| 2245 | // This is used by Enterprise code to control the functionality of this route. |
| 2246 | // Namely, disabling the route using `CODER_BROWSER_ONLY`. |
| 2247 | override := api.WorkspaceClientCoordinateOverride.Load() |
| 2248 | if override != nil { |
| 2249 | overrideFunc := *override |
| 2250 | if overrideFunc != nil && overrideFunc(rw) { |
| 2251 | return |
| 2252 | } |
| 2253 | } |
| 2254 | |
| 2255 | version := "2.0" |
| 2256 | qv := r.URL.Query().Get("version") |
| 2257 | if qv != "" { |
| 2258 | version = qv |
| 2259 | } |
| 2260 | if err := proto.CurrentVersion.Validate(version); err != nil { |
| 2261 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2262 | Message: "Unknown or unsupported API version", |
| 2263 | Validations: []codersdk.ValidationError{ |
| 2264 | {Field: "version", Detail: err.Error()}, |
| 2265 | }, |
| 2266 | }) |
| 2267 | return |
| 2268 | } |
| 2269 | |
| 2270 | peerID, err := api.handleResumeToken(ctx, rw, r) |
| 2271 | if err != nil { |
| 2272 | // handleResumeToken has already written the response. |
| 2273 | return |
| 2274 | } |
| 2275 | |
| 2276 | // Used to authorize tunnel request |
| 2277 | sshPrep, err := api.HTTPAuth.AuthorizeSQLFilter(r, policy.ActionSSH, rbac.ResourceWorkspace.Type) |
| 2278 | if err != nil { |
| 2279 | httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 2280 | Message: "Internal error preparing sql filter.", |
| 2281 | Detail: err.Error(), |
| 2282 | }) |
| 2283 | return |
| 2284 | } |
| 2285 | |
| 2286 | api.WebsocketWaitMutex.Lock() |
| 2287 | api.WebsocketWaitGroup.Add(1) |
| 2288 | api.WebsocketWaitMutex.Unlock() |
| 2289 | defer api.WebsocketWaitGroup.Done() |
| 2290 | |
| 2291 | conn, err := websocket.Accept(rw, r, nil) |
| 2292 | if err != nil { |
| 2293 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 2294 | Message: "Failed to accept websocket.", |
| 2295 | Detail: err.Error(), |
| 2296 | }) |
| 2297 | return |
| 2298 | } |
| 2299 | ctx, wsNetConn := codersdk.WebsocketNetConn(ctx, conn, websocket.MessageBinary) |
nothing calls this directly
no test coverage detected