mirror of
https://github.com/stakater/Reloader.git
synced 2026-08-23 22:16:45 +00:00
feat: Introduce a Generic ResourceReconciler and a generic BaseWorkload to de-duplicate a lot of code
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// Package http provides shared HTTP client functionality.
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultTimeout is the default HTTP client timeout.
|
||||
DefaultTimeout = 30 * time.Second
|
||||
|
||||
// AlertingTimeout is the shorter timeout used for alerting.
|
||||
AlertingTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
// ClientConfig configures an HTTP client.
|
||||
type ClientConfig struct {
|
||||
// Timeout for HTTP requests.
|
||||
Timeout time.Duration
|
||||
|
||||
// ProxyURL is an optional proxy URL.
|
||||
ProxyURL string
|
||||
|
||||
// MaxIdleConns controls the maximum number of idle connections.
|
||||
MaxIdleConns int
|
||||
|
||||
// MaxIdleConnsPerHost controls the maximum idle connections per host.
|
||||
MaxIdleConnsPerHost int
|
||||
|
||||
// IdleConnTimeout is the maximum time an idle connection remains open.
|
||||
IdleConnTimeout time.Duration
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default HTTP client configuration.
|
||||
func DefaultConfig() ClientConfig {
|
||||
return ClientConfig{
|
||||
Timeout: DefaultTimeout,
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// NewClient creates a new HTTP client with the given configuration.
|
||||
func NewClient(cfg ClientConfig) *http.Client {
|
||||
transport := &http.Transport{
|
||||
MaxIdleConns: cfg.MaxIdleConns,
|
||||
MaxIdleConnsPerHost: cfg.MaxIdleConnsPerHost,
|
||||
IdleConnTimeout: cfg.IdleConnTimeout,
|
||||
}
|
||||
|
||||
if cfg.ProxyURL != "" {
|
||||
if proxy, err := url.Parse(cfg.ProxyURL); err == nil {
|
||||
transport.Proxy = http.ProxyURL(proxy)
|
||||
}
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: cfg.Timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDefaultClient creates an HTTP client with default configuration.
|
||||
func NewDefaultClient() *http.Client {
|
||||
return NewClient(DefaultConfig())
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
cfg := DefaultConfig()
|
||||
|
||||
if cfg.Timeout != DefaultTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", DefaultTimeout, cfg.Timeout)
|
||||
}
|
||||
if cfg.MaxIdleConns != 100 {
|
||||
t.Errorf("expected MaxIdleConns 100, got %d", cfg.MaxIdleConns)
|
||||
}
|
||||
if cfg.MaxIdleConnsPerHost != 10 {
|
||||
t.Errorf("expected MaxIdleConnsPerHost 10, got %d", cfg.MaxIdleConnsPerHost)
|
||||
}
|
||||
if cfg.IdleConnTimeout != 90*time.Second {
|
||||
t.Errorf("expected IdleConnTimeout 90s, got %v", cfg.IdleConnTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewClient(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg ClientConfig
|
||||
wantNil bool
|
||||
}{
|
||||
{
|
||||
name: "default config",
|
||||
cfg: DefaultConfig(),
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "custom timeout",
|
||||
cfg: ClientConfig{
|
||||
Timeout: 5 * time.Second,
|
||||
MaxIdleConns: 50,
|
||||
MaxIdleConnsPerHost: 5,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
},
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "with proxy",
|
||||
cfg: ClientConfig{
|
||||
Timeout: DefaultTimeout,
|
||||
ProxyURL: "http://proxy.example.com:8080",
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
},
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "with invalid proxy URL",
|
||||
cfg: ClientConfig{
|
||||
Timeout: DefaultTimeout,
|
||||
ProxyURL: "://invalid",
|
||||
MaxIdleConns: 100,
|
||||
MaxIdleConnsPerHost: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
},
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "zero values",
|
||||
cfg: ClientConfig{
|
||||
Timeout: 0,
|
||||
},
|
||||
wantNil: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
client := NewClient(tt.cfg)
|
||||
|
||||
if tt.wantNil && client != nil {
|
||||
t.Error("expected nil client")
|
||||
}
|
||||
if !tt.wantNil && client == nil {
|
||||
t.Error("expected non-nil client")
|
||||
}
|
||||
|
||||
if client != nil {
|
||||
if client.Timeout != tt.cfg.Timeout {
|
||||
t.Errorf("expected timeout %v, got %v", tt.cfg.Timeout, client.Timeout)
|
||||
}
|
||||
|
||||
transport, ok := client.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
t.Fatal("expected *http.Transport")
|
||||
}
|
||||
if transport.MaxIdleConns != tt.cfg.MaxIdleConns {
|
||||
t.Errorf("expected MaxIdleConns %d, got %d", tt.cfg.MaxIdleConns, transport.MaxIdleConns)
|
||||
}
|
||||
if transport.MaxIdleConnsPerHost != tt.cfg.MaxIdleConnsPerHost {
|
||||
t.Errorf("expected MaxIdleConnsPerHost %d, got %d", tt.cfg.MaxIdleConnsPerHost, transport.MaxIdleConnsPerHost)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDefaultClient(t *testing.T) {
|
||||
client := NewDefaultClient()
|
||||
|
||||
if client == nil {
|
||||
t.Fatal("expected non-nil client")
|
||||
}
|
||||
|
||||
if client.Timeout != DefaultTimeout {
|
||||
t.Errorf("expected timeout %v, got %v", DefaultTimeout, client.Timeout)
|
||||
}
|
||||
|
||||
transport, ok := client.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
t.Fatal("expected *http.Transport")
|
||||
}
|
||||
|
||||
if transport.MaxIdleConns != 100 {
|
||||
t.Errorf("expected MaxIdleConns 100, got %d", transport.MaxIdleConns)
|
||||
}
|
||||
if transport.MaxIdleConnsPerHost != 10 {
|
||||
t.Errorf("expected MaxIdleConnsPerHost 10, got %d", transport.MaxIdleConnsPerHost)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstants(t *testing.T) {
|
||||
if DefaultTimeout != 30*time.Second {
|
||||
t.Errorf("expected DefaultTimeout 30s, got %v", DefaultTimeout)
|
||||
}
|
||||
if AlertingTimeout != 10*time.Second {
|
||||
t.Errorf("expected AlertingTimeout 10s, got %v", AlertingTimeout)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user