feat: rename HttpCustomizer to HttpTransportCustomizer and make it return http.Transport that is later used (#30)
* feat: rename HttpCustomizer to HttpTransportCustomizer and make it return http.Transport that is later used * linting
This commit is contained in:
committed by
GitHub
parent
e25b426a84
commit
7c7ef98c03
@@ -15,6 +15,9 @@ ij_smart_tabs = false
|
|||||||
ij_wrap_on_typing = false
|
ij_wrap_on_typing = false
|
||||||
ij_any_block_comment_add_space = true
|
ij_any_block_comment_add_space = true
|
||||||
|
|
||||||
|
[*.go]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
[*.conf]
|
[*.conf]
|
||||||
ij_continuation_indent_size = 2
|
ij_continuation_indent_size = 2
|
||||||
|
|
||||||
|
|||||||
@@ -84,14 +84,14 @@ List of available client configuration options is available [here](https://pkg.g
|
|||||||
|
|
||||||
### Customizing HTTP Client
|
### Customizing HTTP Client
|
||||||
|
|
||||||
You can customize underlying HTTP client by using `HttpCustomizer` interface:
|
You can customize underlying HTTP client by using `HttpTransportCustomizer` interface:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
c, err := unifi.NewClient(&unifi.ClientConfig{
|
c, err := unifi.NewClient(&unifi.ClientConfig{
|
||||||
...
|
...
|
||||||
HttpCustomizer: func(transport *http.Transport) error {
|
HttpTransportCustomizer: func(transport *http.Transport) (*http.Transport, error) {
|
||||||
transport.MaxIdleConns = 10
|
transport.MaxIdleConns = 10
|
||||||
return nil
|
return transport, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -57,29 +57,6 @@ if err != nil {
|
|||||||
These helper methods abstract away the boilerplate of manually constructing HTTP requests and processing responses, allowing you to focus on your application's logic while leveraging built-in
|
These helper methods abstract away the boilerplate of manually constructing HTTP requests and processing responses, allowing you to focus on your application's logic while leveraging built-in
|
||||||
validation and error handling provided by the SDK.
|
validation and error handling provided by the SDK.
|
||||||
|
|
||||||
## Customizing the HTTP Client
|
|
||||||
|
|
||||||
While the basic configuration allows simple modifications, you can fully customize the underlying HTTP client for more
|
|
||||||
control over connection settings, proxy configuration, TLS settings, and connection pooling.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```go
|
|
||||||
c, err := unifi.NewClient(&unifi.ClientConfig{
|
|
||||||
BaseURL: "https://unifi.localdomain",
|
|
||||||
APIKey: "your-api-key",
|
|
||||||
HttpCustomizer: func (transport *http.Transport) error {
|
|
||||||
transport.MaxIdleConns = 20
|
|
||||||
transport.IdleConnTimeout = 90 * time.Second
|
|
||||||
// Customize TLS settings or add a proxy configuration
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error creating client: %v", err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interceptors and Middleware
|
## Interceptors and Middleware
|
||||||
|
|
||||||
Interceptors provide hooks into the request/response cycle and can be used for logging, metrics collection, or modifying
|
Interceptors provide hooks into the request/response cycle and can be used for logging, metrics collection, or modifying
|
||||||
|
|||||||
@@ -58,16 +58,17 @@ if err != nil {
|
|||||||
|
|
||||||
## Customizing the HTTP Client
|
## Customizing the HTTP Client
|
||||||
|
|
||||||
You can provide your own HTTP client configuration using the `HttpCustomizer` callback. This is useful if you need to tweak connection settings like timeouts, idle connection settings, or TLS configurations:
|
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:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
c, err := unifi.NewClient(&unifi.ClientConfig{
|
c, err := unifi.NewClient(&unifi.ClientConfig{
|
||||||
BaseURL: "https://unifi.localdomain",
|
BaseURL: "https://unifi.localdomain",
|
||||||
APIKey: "your-api-key",
|
APIKey: "your-api-key",
|
||||||
HttpCustomizer: func(transport *http.Transport) error {
|
HttpTransportCustomizer: func(transport *http.Transport) (*http.Transport, error) {
|
||||||
transport.MaxIdleConns = 10
|
transport.MaxIdleConns = 10
|
||||||
// Customize TLS settings, proxy, etc. as needed
|
// Customize TLS settings, proxy, etc. as needed
|
||||||
return nil
|
// You can also create new instance of transport and return it, instead of customizing pre-configured
|
||||||
|
return transport, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -132,14 +133,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// customTransportCustomizer customizes the HTTP transport, e.g., setting idle connection limits and TLS options.
|
// customTransportCustomizer customizes the HTTP transport, e.g., setting idle connection limits and TLS options.
|
||||||
func customTransportCustomizer(transport *http.Transport) error {
|
func customTransportCustomizer(transport *http.Transport) (*http.Transport, error) {
|
||||||
transport.MaxIdleConns = 50
|
transport.MaxIdleConns = 50
|
||||||
transport.IdleConnTimeout = 120 * time.Second
|
transport.IdleConnTimeout = 120 * time.Second
|
||||||
// Set a custom TLS configuration
|
// Set a custom TLS configuration
|
||||||
transport.TLSClientConfig = &tls.Config{
|
transport.TLSClientConfig = &tls.Config{
|
||||||
MinVersion: tls.VersionTLS12,
|
MinVersion: tls.VersionTLS12,
|
||||||
}
|
}
|
||||||
return nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// myErrorHandler implements a custom error handler for HTTP responses.
|
// myErrorHandler implements a custom error handler for HTTP responses.
|
||||||
@@ -175,7 +176,7 @@ func main() {
|
|||||||
Timeout: 30 * time.Second, // Maximum duration to wait for a response
|
Timeout: 30 * time.Second, // Maximum duration to wait for a response
|
||||||
VerifySSL: true, // Enable SSL certificate verification
|
VerifySSL: true, // Enable SSL certificate verification
|
||||||
Interceptors: []unifi.ClientInterceptor{&customInterceptor{}}, // Custom interceptors for request/response manipulation
|
Interceptors: []unifi.ClientInterceptor{&customInterceptor{}}, // Custom interceptors for request/response manipulation
|
||||||
HttpCustomizer: customTransportCustomizer, // Function to customize the underlying HTTP transport
|
HttpTransportCustomizer: customTransportCustomizer, // Function to customize the underlying HTTP transport
|
||||||
UserAgent: "MyCustomAgent/1.0", // Custom User-Agent string
|
UserAgent: "MyCustomAgent/1.0", // Custom User-Agent string
|
||||||
ErrorHandler: &myErrorHandler{}, // Custom error handler for processing HTTP response errors
|
ErrorHandler: &myErrorHandler{}, // Custom error handler for processing HTTP response errors
|
||||||
UseLocking: true, // Enable internal locking for safe concurrent request processing
|
UseLocking: true, // Enable internal locking for safe concurrent request processing
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ const (
|
|||||||
DefaultValidation validationMode = SoftValidation // TODO: change to hard in next major version
|
DefaultValidation validationMode = SoftValidation // TODO: change to hard in next major version
|
||||||
)
|
)
|
||||||
|
|
||||||
// HttpCustomizer is a function type for customizing the HTTP transport.
|
// HttpTransportCustomizer is a function type for customizing the HTTP transport.
|
||||||
// It receives a pointer to an http.Transport and returns an error if customization fails.
|
// It receives a pointer to an http.Transport and returns an error if customization fails.
|
||||||
type HttpCustomizer func(transport *http.Transport) error
|
type HttpTransportCustomizer func(transport *http.Transport) (*http.Transport, error)
|
||||||
|
|
||||||
// ResponseErrorHandler defines a method for handling HTTP response errors.
|
// ResponseErrorHandler defines a method for handling HTTP response errors.
|
||||||
// HandleError processes the HTTP response and returns an error if the response indicates failure.
|
// HandleError processes the HTTP response and returns an error if the response indicates failure.
|
||||||
@@ -53,25 +53,25 @@ 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.
|
||||||
HttpCustomizer: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).
|
||||||
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
|
||||||
HttpCustomizer HttpCustomizer
|
HttpTransportCustomizer HttpTransportCustomizer
|
||||||
UserAgent string
|
UserAgent string
|
||||||
ErrorHandler ResponseErrorHandler
|
ErrorHandler ResponseErrorHandler
|
||||||
UseLocking bool
|
UseLocking bool
|
||||||
ValidationMode validationMode `validate:"omitempty,oneof=soft hard disable"`
|
ValidationMode validationMode `validate:"omitempty,oneof=soft hard disable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Credentials abstracts authentication credentials.
|
// Credentials abstracts authentication credentials.
|
||||||
@@ -158,8 +158,8 @@ func newClientFromConfig(config *ClientConfig, v *validator) (*client, error) {
|
|||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: !config.VerifySSL},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: !config.VerifySSL},
|
||||||
}
|
}
|
||||||
if config.HttpCustomizer != nil {
|
if config.HttpTransportCustomizer != nil {
|
||||||
if err = config.HttpCustomizer(transport); err != nil {
|
if transport, err = config.HttpTransportCustomizer(transport); err != nil {
|
||||||
return nil, fmt.Errorf("failed customizing HTTP transport: %w", err)
|
return nil, fmt.Errorf("failed customizing HTTP transport: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ func TestCustomizeHttpClient(t *testing.T) {
|
|||||||
_, err := NewClient(&ClientConfig{
|
_, err := NewClient(&ClientConfig{
|
||||||
URL: localUrl,
|
URL: localUrl,
|
||||||
APIKey: "test-key",
|
APIKey: "test-key",
|
||||||
HttpCustomizer: func(transport *http.Transport) error {
|
HttpTransportCustomizer: func(transport *http.Transport) (*http.Transport, error) {
|
||||||
called = true
|
called = true
|
||||||
return nil
|
return transport, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -850,16 +850,16 @@ func TestLoginWithAPIKeyDirect(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpCustomizerError(t *testing.T) {
|
func TestHttpTransportCustomizerError(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
customizer := func(transport *http.Transport) error {
|
customizer := func(transport *http.Transport) (*http.Transport, error) {
|
||||||
return errors.New("customization failed")
|
return nil, errors.New("customization failed")
|
||||||
}
|
}
|
||||||
_, err := NewClient(&ClientConfig{
|
_, err := NewClient(&ClientConfig{
|
||||||
URL: testUrl,
|
URL: testUrl,
|
||||||
APIKey: "test-key",
|
APIKey: "test-key",
|
||||||
VerifySSL: false,
|
VerifySSL: false,
|
||||||
HttpCustomizer: customizer,
|
HttpTransportCustomizer: customizer,
|
||||||
})
|
})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "failed customizing HTTP transport")
|
assert.Contains(t, err.Error(), "failed customizing HTTP transport")
|
||||||
|
|||||||
Reference in New Issue
Block a user