feat: allow creating own http.RoundTripper for http.Client with HttpRoundTripperProvider when customizing pre-configured http.Transport with HttpTransportCustomizer is not sufficient (#31)
feat: allow creating own http.RoundTripper for http.Client with `HttpRoundTripperProvider` when customizing pre-configured http.Transport with `HttpTransportCustomizer` is not sufficient
This commit is contained in:
committed by
GitHub
parent
7c7ef98c03
commit
d3a3d5a342
@@ -58,7 +58,17 @@ if err != nil {
|
|||||||
|
|
||||||
## Customizing the HTTP Client
|
## Customizing the HTTP Client
|
||||||
|
|
||||||
You can provide your own HTTP client configuration using the `HttpTransportCustomizer` callback. This is useful if you need to tweak connection settings like timeouts, idle connection settings, or TLS configurations:
|
There are two ways to customize the HTTP client used by the UniFi client:
|
||||||
|
1. Using the `HttpTransportCustomizer`.
|
||||||
|
2. Using the `HttpRoundTripperProvider`.
|
||||||
|
|
||||||
|
Those methods are mutually exclusive, and only one can be used at a time. If both are provided, the `HttpRoundTripperProvider` takes precedence,
|
||||||
|
unless it returns `nil`, in which case the `HttpTransportCustomizer` is used if defined (or default transport is used).
|
||||||
|
|
||||||
|
### Using `HttpTransportCustomizer`
|
||||||
|
|
||||||
|
You can provide your own HTTP client transport configuration using the `HttpTransportCustomizer` callback. This is useful if you need to tweak connection settings like timeouts, idle connection settings,
|
||||||
|
or TLS configurations:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
c, err := unifi.NewClient(&unifi.ClientConfig{
|
c, err := unifi.NewClient(&unifi.ClientConfig{
|
||||||
@@ -76,6 +86,21 @@ if err != nil {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Using `HttpRoundTripperProvider`
|
||||||
|
|
||||||
|
You can provide your own HTTP client configuration using the `HttpRoundTripperProvider` callback. This is useful if you need to create a custom round tripper, when `http.Transport` is not enough:
|
||||||
|
|
||||||
|
```go
|
||||||
|
c, err := unifi.NewClient(&unifi.ClientConfig{
|
||||||
|
BaseURL: "https://unifi.localdomain",
|
||||||
|
APIKey: "your-api-key",
|
||||||
|
HttpRoundTripperProvider: func() http.RoundTripper {
|
||||||
|
// Create a custom HTTP Round Tripper instance
|
||||||
|
return &http.Transport{}, nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
## Using Interceptors
|
## Using Interceptors
|
||||||
|
|
||||||
Interceptors let you hook into the request and response flow. They can be used for logging, metrics, or modifying requests/responses.
|
Interceptors let you hook into the request and response flow. They can be used for logging, metrics, or modifying requests/responses.
|
||||||
|
|||||||
@@ -53,25 +53,27 @@ Fields:
|
|||||||
Timeout: The maximum duration to wait for responses; default is no timeout.
|
Timeout: The maximum duration to wait for responses; default is no timeout.
|
||||||
VerifySSL: When false, disables SSL certificate verification.
|
VerifySSL: When false, disables SSL certificate verification.
|
||||||
Interceptors: A slice of ClientInterceptor implementations that can modify requests and responses.
|
Interceptors: A slice of ClientInterceptor implementations that can modify requests and responses.
|
||||||
HttpTransportCustomizer:An optional function to customize the HTTP transport (e.g., for custom TLS settings).
|
HttpTransportCustomizer: An optional function to customize the HTTP transport (e.g., for custom TLS settings).
|
||||||
|
HttpRoundTripperProvider: A function that returns a http.RoundTripper for customizing the HTTP client. If both HttpTransportCustomizer and HttpRoundTripperProvider are provided, HttpRoundTripperProvider takes precedence.
|
||||||
UserAgent: The User-Agent header string for outgoing HTTP requests.
|
UserAgent: The User-Agent header string for outgoing HTTP requests.
|
||||||
ErrorHandler: A custom handler for processing HTTP response errors.
|
ErrorHandler: A custom handler for processing HTTP response errors.
|
||||||
UseLocking: If true, enables internal locking for concurrent request processing.
|
UseLocking: If true, enables internal locking for concurrent request processing.
|
||||||
ValidationMode:The mode for validating request bodies. Can be "soft", "hard", or "disable".
|
ValidationMode:The mode for validating request bodies. Can be "soft", "hard", or "disable".
|
||||||
*/
|
*/
|
||||||
type ClientConfig struct {
|
type ClientConfig struct {
|
||||||
URL string `validate:"required,http_url"`
|
URL string `validate:"required,http_url"`
|
||||||
APIKey string `validate:"required_without_all=User Password"`
|
APIKey string `validate:"required_without_all=User Password"`
|
||||||
User string `validate:"excluded_with=APIKey,required_with=Password"`
|
User string `validate:"excluded_with=APIKey,required_with=Password"`
|
||||||
Password string `validate:"excluded_with=APIKey,required_with=User"`
|
Password string `validate:"excluded_with=APIKey,required_with=User"`
|
||||||
Timeout time.Duration // How long to wait for replies, default: forever.
|
Timeout time.Duration // How long to wait for replies, default: forever.
|
||||||
VerifySSL bool
|
VerifySSL bool
|
||||||
Interceptors []ClientInterceptor
|
Interceptors []ClientInterceptor
|
||||||
HttpTransportCustomizer HttpTransportCustomizer
|
HttpTransportCustomizer HttpTransportCustomizer
|
||||||
UserAgent string
|
HttpRoundTripperProvider func() http.RoundTripper
|
||||||
ErrorHandler ResponseErrorHandler
|
UserAgent string
|
||||||
UseLocking bool
|
ErrorHandler ResponseErrorHandler
|
||||||
ValidationMode validationMode `validate:"omitempty,oneof=soft hard disable"`
|
UseLocking bool
|
||||||
|
ValidationMode validationMode `validate:"omitempty,oneof=soft hard disable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credentials abstracts authentication credentials.
|
// Credentials abstracts authentication credentials.
|
||||||
@@ -152,20 +154,27 @@ func parseBaseURL(base string) (*url.URL, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newClientFromConfig(config *ClientConfig, v *validator) (*client, error) {
|
func newClientFromConfig(config *ClientConfig, v *validator) (*client, error) {
|
||||||
|
var rt http.RoundTripper
|
||||||
var err error
|
var err error
|
||||||
config.URL = strings.TrimRight(config.URL, "/")
|
config.URL = strings.TrimRight(config.URL, "/")
|
||||||
transport := &http.Transport{
|
if config.HttpRoundTripperProvider != nil {
|
||||||
Proxy: http.ProxyFromEnvironment,
|
rt = config.HttpRoundTripperProvider()
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: !config.VerifySSL},
|
|
||||||
}
|
}
|
||||||
if config.HttpTransportCustomizer != nil {
|
if rt == nil {
|
||||||
if transport, err = config.HttpTransportCustomizer(transport); err != nil {
|
transport := &http.Transport{
|
||||||
return nil, fmt.Errorf("failed customizing HTTP transport: %w", err)
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: !config.VerifySSL},
|
||||||
}
|
}
|
||||||
|
if config.HttpTransportCustomizer != nil {
|
||||||
|
if transport, err = config.HttpTransportCustomizer(transport); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed customizing HTTP transport: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rt = transport
|
||||||
}
|
}
|
||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Timeout: config.Timeout,
|
Timeout: config.Timeout,
|
||||||
Transport: transport,
|
Transport: rt,
|
||||||
}
|
}
|
||||||
if config.APIKey == "" {
|
if config.APIKey == "" {
|
||||||
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
|
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
|
||||||
|
|||||||
Reference in New Issue
Block a user