Files
ctrld/cmd/cli/control_client.go
T

61 lines
1.7 KiB
Go

package cli
import (
"context"
"io"
"net"
"net/http"
"net/url"
"strings"
"time"
)
// controlClient represents an HTTP client for communicating with the control server
type controlClient struct {
c *http.Client
}
// newControlClient creates a new control client with Unix socket transport
func newControlClient(addr string) *controlClient {
return &controlClient{c: &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
d := net.Dialer{}
return d.DialContext(ctx, "unix", addr)
},
},
Timeout: time.Second * 30,
}}
}
func (c *controlClient) post(path string, data io.Reader) (*http.Response, error) {
// A log send uploads many megabytes, so it needs more time than the other
// calls.
if isSendLogsPath(path) {
c.c.Timeout = time.Minute * 5
}
return c.c.Post("http://unix"+path, contentTypeJson, data)
}
// isSendLogsPath reports whether path addresses the log send handler. The path
// can carry a query, so the comparison takes the path alone. A path that does
// not parse keeps the prefix rule, because it still reaches that handler.
func isSendLogsPath(path string) bool {
parsed, err := url.Parse(path)
if err != nil {
return strings.HasPrefix(path, sendLogsPath)
}
return parsed.Path == sendLogsPath
}
// postStream sends a POST request with no timeout, suitable for long-lived streaming connections.
func (c *controlClient) postStream(path string, data io.Reader) (*http.Response, error) {
c.c.Timeout = 0
return c.c.Post("http://unix"+path, contentTypeJson, data)
}
// deactivationRequest represents request for validating deactivation pin.
type deactivationRequest struct {
Pin int64 `json:"pin"`
}