generated from deploymenttheory/Template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
client.go
111 lines (94 loc) · 3.76 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// httpclient/client.go
/* The `http_client` package provides a configurable HTTP client tailored for interacting with specific APIs.
It supports different authentication methods, including "bearer" and "oauth". The client is designed with a
focus on concurrency management, structured error handling, and flexible configuration options.
The package offers a default timeout, custom backoff strategies, dynamic rate limiting,
and detailed logging capabilities. The main `Client` structure encapsulates all necessary components,
like the baseURL, authentication details, and an embedded standard HTTP client. */
package httpclient
import (
"fmt"
"net/http"
"time"
"github.com/deploymenttheory/go-api-http-client/concurrency"
"github.com/deploymenttheory/go-api-http-client/logger"
"github.com/deploymenttheory/go-api-http-client/redirecthandler"
"go.uber.org/zap"
)
// TODO all struct comments
// Master struct/object
type Client struct {
config ClientConfig
http *http.Client
AuthToken string
AuthTokenExpiry time.Time
Logger logger.Logger
Concurrency *concurrency.ConcurrencyHandler
Integration *APIIntegration
}
// Options/Variables for Client
type ClientConfig struct {
Integration APIIntegration
HideSensitiveData bool
CustomCookies []*http.Cookie
MaxRetryAttempts int
MaxConcurrentRequests int
EnableDynamicRateLimiting bool
CustomTimeout time.Duration
TokenRefreshBufferPeriod time.Duration
TotalRetryDuration time.Duration // TODO do we need this now it's in the integration?
FollowRedirects bool
MaxRedirects int
EnableConcurrencyManagement bool
}
// BuildClient creates a new HTTP client with the provided configuration.
func BuildClient(config ClientConfig, populateDefaultValues bool, log logger.Logger) (*Client, error) {
err := validateClientConfig(config, populateDefaultValues)
if err != nil {
return nil, fmt.Errorf("invalid configuration: %v", err)
}
log.Info(fmt.Sprintf("initializing new http client, auth: %s", config.Integration.GetFQDN()))
httpClient := &http.Client{
Timeout: config.CustomTimeout,
}
// TODO refactor redirects
if err := redirecthandler.SetupRedirectHandler(httpClient, config.FollowRedirects, config.MaxRedirects, log); err != nil {
log.Error("Failed to set up redirect handler", zap.Error(err))
return nil, err
}
var concurrencyHandler *concurrency.ConcurrencyHandler
if config.EnableConcurrencyManagement {
concurrencyMetrics := &concurrency.ConcurrencyMetrics{}
concurrencyHandler = concurrency.NewConcurrencyHandler(
config.MaxConcurrentRequests,
log,
concurrencyMetrics,
)
} else {
concurrencyHandler = nil
}
client := &Client{
Integration: &config.Integration,
http: httpClient,
config: config,
Logger: log,
Concurrency: concurrencyHandler,
}
if len(client.config.CustomCookies) > 0 {
client.loadCustomCookies(config.CustomCookies)
}
log.Debug("New API client initialized",
zap.String("Authentication Method", (*client.Integration).GetAuthMethodDescriptor()),
zap.Bool("Hide Sensitive Data In Logs", config.HideSensitiveData),
zap.Int("Max Retry Attempts", config.MaxRetryAttempts),
zap.Bool("Enable Dynamic Rate Limiting", config.EnableDynamicRateLimiting),
zap.Int("Max Concurrent Requests", config.MaxConcurrentRequests),
zap.Bool("Follow Redirects", config.FollowRedirects),
zap.Int("Max Redirects", config.MaxRedirects),
zap.Duration("Token Refresh Buffer Period", config.TokenRefreshBufferPeriod),
zap.Duration("Total Retry Duration", config.TotalRetryDuration),
zap.Duration("Custom Timeout", config.CustomTimeout),
zap.Bool("Enable Concurrency Management", config.EnableConcurrencyManagement),
)
return client, nil
}