Skip to content

Commit

Permalink
introduce webclient.ReusableClient (#49296)
Browse files Browse the repository at this point in the history
  • Loading branch information
hugoShaka authored Nov 27, 2024
1 parent a1cdc9a commit 7d102ca
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions api/client/webclient/webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ func Find(cfg *Config) (*PingResponse, error) {
}
defer clt.CloseIdleConnections()

return findWithClient(cfg, clt)
}

func findWithClient(cfg *Config, clt *http.Client) (*PingResponse, error) {
ctx, span := cfg.TraceProvider.Tracer("webclient").Start(cfg.Context, "webclient/Find")
defer span.End()

Expand Down Expand Up @@ -214,6 +218,10 @@ func Ping(cfg *Config) (*PingResponse, error) {
}
defer clt.CloseIdleConnections()

return pingWithClient(cfg, clt)
}

func pingWithClient(cfg *Config, clt *http.Client) (*PingResponse, error) {
ctx, span := cfg.TraceProvider.Tracer("webclient").Start(cfg.Context, "webclient/Ping")
defer span.End()

Expand Down Expand Up @@ -267,13 +275,18 @@ func Ping(cfg *Config) (*PingResponse, error) {
return pr, nil
}

// GetMOTD retrieves the Message Of The Day from the web proxy.
func GetMOTD(cfg *Config) (*MotD, error) {
clt, err := newWebClient(cfg)
if err != nil {
return nil, trace.Wrap(err)
}
defer clt.CloseIdleConnections()

return getMOTDWithClient(cfg, clt)
}

func getMOTDWithClient(cfg *Config, clt *http.Client) (*MotD, error) {
ctx, span := cfg.TraceProvider.Tracer("webclient").Start(cfg.Context, "webclient/GetMOTD")
defer span.End()

Expand Down Expand Up @@ -302,6 +315,60 @@ func GetMOTD(cfg *Config) (*MotD, error) {
return motd, nil
}

// NewReusableClient creates a reusable webproxy client. If you need to do a single call,
// use the webclient.Ping or webclient.Find functions instead.
func NewReusableClient(cfg *Config) (*ReusableClient, error) {
// no need to check and set config defaults, this happens in newWebClient
client, err := newWebClient(cfg)
if err != nil {
return nil, trace.Wrap(err, "building new web client")
}

return &ReusableClient{
client: client,
config: cfg,
}, nil
}

// ReusableClient is a webproxy client that allows the caller to make multiple calls
// without having to buildi a new HTTP client each time.
// Before retiring the client, you must make sure no calls are still in-flight, then call
// ReusableClient.CloseIdleConnections().
type ReusableClient struct {
client *http.Client
config *Config
}

// Find fetches discovery data by connecting to the given web proxy address.
// It is designed to fetch proxy public addresses without any inefficiencies.
func (c *ReusableClient) Find() (*PingResponse, error) {
return findWithClient(c.config, c.client)
}

// Ping serves two purposes. The first is to validate the HTTP endpoint of a
// Teleport proxy. This leads to better user experience: users get connection
// errors before being asked for passwords. The second is to return the form
// of authentication that the server supports. This also leads to better user
// experience: users only get prompted for the type of authentication the server supports.
func (c *ReusableClient) Ping() (*PingResponse, error) {
return pingWithClient(c.config, c.client)
}

// GetMOTD retrieves the Message Of The Day from the web proxy.
func (c *ReusableClient) GetMOTD() (*MotD, error) {
return getMOTDWithClient(c.config, c.client)
}

// CloseIdleConnections closes any connections on its [Transport] which
// were previously connected from previous requests but are now
// sitting idle in a "keep-alive" state. It does not interrupt any
// connections currently in use.
//
// This must be run before retiring the ReusableClient.
func (c *ReusableClient) CloseIdleConnections() {
c.client.CloseIdleConnections()
}

// MotD holds data about the current message of the day.
type MotD struct {
Text string
Expand Down

0 comments on commit 7d102ca

Please sign in to comment.