MCPcopy Index your code
hub / github.com/coder/coder / AgentReconnectingPTY

Method AgentReconnectingPTY

codersdk/workspacesdk/workspacesdk.go:346–396  ·  view source on GitHub ↗

AgentReconnectingPTY spawns a PTY that reconnects using the token provided. It communicates using `agent.ReconnectingPTYRequest` marshaled as JSON. Responses are PTY output that can be rendered.

(ctx context.Context, opts WorkspaceAgentReconnectingPTYOpts)

Source from the content-addressed store, hash-verified

344// It communicates using `agent.ReconnectingPTYRequest` marshaled as JSON.
345// Responses are PTY output that can be rendered.
346func (c *Client) AgentReconnectingPTY(ctx context.Context, opts WorkspaceAgentReconnectingPTYOpts) (net.Conn, error) {
347 serverURL, err := c.client.URL.Parse(fmt.Sprintf("/api/v2/workspaceagents/%s/pty", opts.AgentID))
348 if err != nil {
349 return nil, xerrors.Errorf("parse url: %w", err)
350 }
351 q := serverURL.Query()
352 q.Set("reconnect", opts.Reconnect.String())
353 q.Set("width", strconv.Itoa(int(opts.Width)))
354 q.Set("height", strconv.Itoa(int(opts.Height)))
355 q.Set("command", opts.Command)
356 if opts.Container != "" {
357 q.Set("container", opts.Container)
358 }
359 if opts.ContainerUser != "" {
360 q.Set("container_user", opts.ContainerUser)
361 }
362 if opts.BackendType != "" {
363 q.Set("backend_type", opts.BackendType)
364 }
365 // If we're using a signed token, set the query parameter.
366 if opts.SignedToken != "" {
367 q.Set(codersdk.SignedAppTokenQueryParameter, opts.SignedToken)
368 }
369 serverURL.RawQuery = q.Encode()
370
371 // Shallow-clone the HTTP client so we never inherit a caller-provided
372 // cookie jar. Non-browser websocket auth uses the Coder-Session-Token
373 // header or a signed-token query param — never cookies. A stale jar
374 // cookie would take precedence on the server (cookies are checked
375 // before headers) and cause spurious 401s.
376 wsHTTPClient := *c.client.HTTPClient
377 wsHTTPClient.Jar = nil
378
379 headers := http.Header{}
380 // If we're not using a signed token, set the session token header.
381 if opts.SignedToken == "" {
382 headers.Set(codersdk.SessionTokenHeader, c.client.SessionToken())
383 }
384 //nolint:bodyclose
385 conn, res, err := websocket.Dial(ctx, serverURL.String(), &websocket.DialOptions{
386 HTTPClient: &wsHTTPClient,
387 HTTPHeader: headers,
388 })
389 if err != nil {
390 if res == nil {
391 return nil, err
392 }
393 return nil, codersdk.ReadBodyAsError(res)
394 }
395 return websocket.NetConn(context.Background(), conn, websocket.MessageBinary), nil
396}
397
398func WithTestOnlyCoderContextResolver(ctx context.Context, r Resolver) context.Context {
399 return context.WithValue(ctx, dnsResolverContextKey{}, r)

Callers 4

testReconnectingPTYFunction · 0.80
handleRPTYFunction · 0.80
RunMethod · 0.80
connectRPTYFunction · 0.80

Calls 8

ReadBodyAsErrorFunction · 0.92
EncodeMethod · 0.80
ParseMethod · 0.65
SetMethod · 0.65
DialMethod · 0.65
ErrorfMethod · 0.45
StringMethod · 0.45
SessionTokenMethod · 0.45

Tested by

no test coverage detected