client

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 27, 2026 License: MIT Imports: 24 Imported by: 0

README

bursthttp

Go Reference Go Report Card CI

High-performance Go HTTP/1.1 client with pipelining and pooling.


bursthttp is a zero-dependency HTTP/1.1 client built for high-throughput workloads. It pipelines multiple requests over a single TCP connection, pools and reuses connections per host, and recycles request/response objects to minimize allocations. Built-in retry, DNS caching, metrics, streaming, proxy support, and graceful shutdown are included out of the box.

Features

  • HTTP/1.1 Pipelining — Send multiple requests on one connection without waiting for responses.
  • Per-Host Connection Pooling — Persistent connections with configurable pool size and idle eviction.
  • Object Poolingsync.Pool-backed request/response reuse for near-zero allocation.
  • Retry with Exponential Backoff — Configurable retries with jitter for transient failures.
  • DNS Caching — In-memory resolution cache with TTL.
  • Pluggable Metrics — Built-in collector with latency percentiles (p50/p95/p99), byte counters, pool events. Implement MetricsCollector for Prometheus/StatsD.
  • Streamingio.ReadCloser response bodies and io.Reader request bodies.
  • Multipart Builder — Helpers for multipart/form-data uploads.
  • Proxy Support — HTTP CONNECT and SOCKS5 (RFC 1928).
  • Gzip — Transparent response decompression and request compression.
  • Graceful Shutdown — Drain in-flight requests before closing.
  • Connection Warm-Up — Pre-establish connections before first request.
  • URL Routing — Route to multiple hosts from a single client.
  • Expect: 100-Continue — Send headers first, body after server confirms.
  • Pre-encoded requests — Cache the header block with BuildPreEncodedHeaderPrefix and Request.PreEncodedHeaderPrefix; send many requests with the same headers without re-encoding.
  • Lock-free connection pool — Host lookup via sync.Map, connection list via atomic.Pointer and CAS (no mutex on the get path).
  • Header zero-copy — Request headers sent with vectored write (net.Buffers); response header values via Response.HeaderBytes(key) as a slice into the raw buffer.
  • Request Scheduler — Opt-in per-host bounded queue with worker goroutine pool; replaces spin-wait with a proper blocking queue for stable latency under overload (EnableScheduler).
  • Async DNS — In-flight deduplication (singleflight), background prefetch at 80% TTL, round-robin IP selection, stale fallback on errors, negative cache for failed lookups (DNSNegativeTTL).
  • Connection Health Scoring — Per-connection latency EWMA and error rate produce a 0–100 score; pool selection prefers higher-scoring connections (EnableHealthScoring).
  • Pipeline Auto-Tuning — Pipeline depth adjusts per connection based on measured latency: fast servers get deeper pipelines, slow servers get shallower ones (EnablePipelineAutoTune).
  • TCP socket tuningTCPFastOpen and TCPReusePort on Linux reduce connection setup cost.
  • Zero External Dependencies — Pure Go stdlib.

Installation

go get github.com/muxover/bursthttp

Requires Go 1.22+.

Quick Start

package main

import (
    "fmt"
    "log"

    bursthttp "github.com/muxover/bursthttp"
)

func main() {
    cfg := bursthttp.DefaultConfig()
    cfg.Host = "httpbin.org"
    cfg.Port = 443
    cfg.UseTLS = true

    client, err := bursthttp.NewClient(cfg)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Stop()

    resp, err := client.Get("/get", nil)
    if err != nil {
        log.Fatal(err)
    }
    defer client.ReleaseResponse(resp)

    fmt.Printf("Status: %d\nBody: %s\n", resp.StatusCode, resp.Body)
}

API Overview

Client Lifecycle
Method Description
NewClient(cfg) Create a client from config
client.Stop() Close all connections immediately
client.GracefulStop(timeout) Drain in-flight requests, then close
client.StartN(n) Pre-establish n connections
Request Methods
Method Description
Get(path, headers) GET request
Post(path, body, headers) POST request
Put(path, body, headers) PUT request
Patch(path, body, headers) PATCH request
Delete(path, headers) DELETE request
Head(path, headers) HEAD request
Options(path, headers) OPTIONS request
GetURL(url, headers) GET to a full URL (auto-routed)
PostURL(url, body, headers) POST to a full URL (auto-routed)
Low-Level API
Method Description
Do(req) Execute a pooled request
DoWithContext(ctx, req) Execute with context cancellation
DoStreaming(ctx, req) Stream response body as io.ReadCloser
DoReader(ctx, method, path, body, size, headers) Send io.Reader body
AcquireRequest() / ReleaseRequest(req) Pool a request object
ReleaseResponse(resp) Return response to pool
Response Helpers
Method Description
resp.Header(key) Get first header value (case-insensitive)
resp.HasHeader(key) Check header existence
resp.HeaderValues(key) Get all values for a header
resp.HeaderBytes(key) Get first header value as []byte (zero-copy)
Observability
Method Description
client.GetHealthyConnections() Count of healthy connections
client.Stats() Snapshot of client state + metrics
GetVersion() Library version string

Configuration

Presets
Preset Pool Pipeline Retry DNS Cache Scheduler Health Scoring Auto-Tune Use Case
DefaultConfig() 512 Yes (10) No No No Yes No General purpose
HighThroughputConfig() 1024 Yes (auto) No Yes Yes Yes Yes 100K+ RPS
ResilientConfig() 512 Yes (10) 3 retries Yes No Yes No Unreliable upstreams
Key Fields
Field Type Default Description
Host string "localhost" Target hostname
Port int 80/443 Target port
UseTLS bool false Enable TLS
PoolSize int 512 Max connections per host
EnablePipelining bool true HTTP/1.1 pipelining
MaxPipelinedRequests int 10 Pipeline depth per connection
ReadTimeout Duration 30s Response read timeout
WriteTimeout Duration 10s Request write timeout
DialTimeout Duration 10s TCP connect timeout
IdleTimeout Duration 90s Idle connection eviction
MaxRetries int 0 Retry attempts (0 = disabled)
RetryBaseDelay Duration 100ms Initial backoff delay
EnableDNSCache bool false In-memory DNS cache
DNSCacheTTL Duration 5m DNS cache entry lifetime
EnableCompression bool false Gzip request compression
ProxyURL string "" HTTP CONNECT proxy
SOCKS5Addr string "" SOCKS5 proxy address
Metrics MetricsCollector nil Pluggable metrics backend
EnableHealthScoring bool true Per-connection latency/error scoring
EnableScheduler bool false Per-host request queue + worker pool
SchedulerWorkers int 0 (=PoolSize) Worker goroutines per host
SchedulerQueueDepth int 0 (=workers×4) Max queued requests per host
EnablePipelineAutoTune bool false Auto-adjust pipeline depth by latency
TCPFastOpen bool false Linux: TCP Fast Open on connect
TCPReusePort bool false Linux: SO_REUSEPORT on sockets
DNSNegativeTTL Duration 5s Cache duration for failed DNS lookups

Architecture

Client
  ├── Scheduler (optional, per-host queue + worker pool)
  ├── Pool (per-host connection pools)
  │     ├── Connection (pipelined or sequential)
  │     │     ├── Health Scoring (latency EWMA + error rate)
  │     │     ├── Pipeline Auto-Tuning (dynamic depth by latency)
  │     │     ├── Writer (request serialization)
  │     │     └── Parser (response parsing, chunked decoding)
  │     └── Idle Evictor
  ├── Dialer
  │     ├── DNS Cache (async, prefetch, round-robin, negative cache)
  │     ├── TCP tuning (FastOpen, ReusePort — Linux)
  │     ├── SOCKS5 Dialer
  │     └── HTTP CONNECT Proxy
  ├── TLS (session caching, handshake timeout)
  ├── Compressor (gzip)
  ├── Retryer (exponential backoff + jitter)
  └── Metrics Collector (pluggable)

Contributing

See CONTRIBUTING.md.

License

Licensed under MIT.


Made with ❤️ by Jax (@muxover)

Documentation

Overview

Package client provides a high-performance HTTP/1.1 client with pipelining, per-host connection pooling, object reuse, retry, DNS caching, metrics, streaming, proxy support, and graceful shutdown. Zero external dependencies.

Create a client with NewClient and a Config (or use DefaultConfig, HighThroughputConfig, ResilientConfig presets). Use convenience methods like Client.Get and Client.Post for common operations, or the low-level Client.Do / Client.DoWithContext for full control with pooled requests.

cfg := client.DefaultConfig()
cfg.Host = "api.example.com"
cfg.Port = 443
cfg.UseTLS = true

c, err := client.NewClient(cfg)
if err != nil {
    log.Fatal(err)
}
defer c.Stop()

resp, err := c.Get("/v1/users", nil)
if err != nil {
    log.Fatal(err)
}
defer c.ReleaseResponse(resp)

Index

Examples

Constants

View Source
const (
	Version           = "v0.1.4"
	VersionMajor      = 0
	VersionMinor      = 1
	VersionPatch      = 4
	VersionPreRelease = ""
)

Variables

View Source
var (
	ErrConnectFailed     = errors.New("connect failed")
	ErrWriteFailed       = errors.New("write failed")
	ErrReadFailed        = errors.New("read failed")
	ErrHeaderTooLarge    = errors.New("response header too large")
	ErrInvalidResponse   = errors.New("invalid response")
	ErrResponseTooLarge  = errors.New("response too large")
	ErrRequestTooLarge   = errors.New("request body too large")
	ErrHeaderBufferSmall = errors.New("header buffer too small")
	ErrTimeout           = errors.New("operation timeout")
	ErrConnectionClosed  = errors.New("connection closed")
	ErrProxyFailed       = errors.New("proxy connection failed")
	ErrInvalidURL        = errors.New("invalid URL")
	ErrInvalidRequest    = errors.New("invalid request")
)

Pre-allocated sentinel errors returned by the library. Use IsTimeout and IsRetryable to classify errors without direct comparison.

Functions

func GetVersion

func GetVersion() string

GetVersion returns the library version.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	v := client.GetVersion()
	fmt.Printf("starts with v: %v\n", v[0] == 'v')
}
Output:
starts with v: true

func IsRetryable

func IsRetryable(err error) bool

IsRetryable checks if an error is retryable.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	fmt.Println(client.IsRetryable(client.ErrConnectFailed))
	fmt.Println(client.IsRetryable(client.ErrInvalidURL))
}
Output:
true
false

func IsTimeout

func IsTimeout(err error) bool

IsTimeout checks if an error is a timeout error. It handles net.Error timeouts, context.DeadlineExceeded, ErrTimeout, and DetailedError with ErrorTypeTimeout — including wrapped errors.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	err := client.ErrTimeout
	fmt.Println(client.IsTimeout(err))
	fmt.Println(client.IsTimeout(nil))
}
Output:
true
false

func LogErrorWithFlag

func LogErrorWithFlag(errType ErrorType, message string, err error, context map[string]interface{}, enableLogging bool) error

LogErrorWithFlag logs a detailed error with type and context if enableLogging is true.

func ReleaseRequest

func ReleaseRequest(req *Request)

ReleaseRequest returns req to the global pool.

func ReleaseResponse

func ReleaseResponse(resp *Response)

ReleaseResponse returns a response to the pool.

func WrapError

func WrapError(errType ErrorType, message string, err error) error

WrapError creates a detailed error without logging (for retry scenarios).

Types

type BuiltinMetrics

type BuiltinMetrics struct {
	// contains filtered or unexported fields
}

BuiltinMetrics is a thread-safe in-memory MetricsCollector included with bursthttp. It provides request counts, latency percentiles, byte counters, and connection pool statistics.

cfg.Metrics = bursthttp.NewBuiltinMetrics()

func NewBuiltinMetrics

func NewBuiltinMetrics() *BuiltinMetrics

NewBuiltinMetrics creates a ready-to-use BuiltinMetrics instance.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	m := client.NewBuiltinMetrics()
	cfg := client.DefaultConfig()
	cfg.Metrics = m

	fmt.Println("metrics configured")
}
Output:
metrics configured

func (*BuiltinMetrics) RecordPoolEvent

func (m *BuiltinMetrics) RecordPoolEvent(event PoolEvent, host string)

RecordPoolEvent implements MetricsCollector.

func (*BuiltinMetrics) RecordRequest

func (m *BuiltinMetrics) RecordRequest(method, host string) time.Time

RecordRequest implements MetricsCollector.

func (*BuiltinMetrics) RecordResponse

func (m *BuiltinMetrics) RecordResponse(method, host string, statusCode int, err error, start time.Time, bytesWritten, bytesRead int64)

RecordResponse implements MetricsCollector.

func (*BuiltinMetrics) RecordRetry

func (m *BuiltinMetrics) RecordRetry()

RecordRetry increments the retry counter. Called by the retry loop.

func (*BuiltinMetrics) Snapshot

func (m *BuiltinMetrics) Snapshot() MetricsSnapshot

Snapshot implements MetricsCollector.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	m := client.NewBuiltinMetrics()
	start := m.RecordRequest("GET", "example.com")
	m.RecordResponse("GET", "example.com", 200, nil, start, 50, 1024)
	m.RecordPoolEvent(client.PoolEventConnCreated, "example.com")

	snap := m.Snapshot()
	fmt.Printf("total: %d, ok: %d\n", snap.RequestsTotal, snap.RequestsOK)
	fmt.Printf("bytes written: %d, read: %d\n", snap.BytesWritten, snap.BytesRead)
	fmt.Printf("conns created: %d\n", snap.ConnsCreated)
}
Output:
total: 1, ok: 1
bytes written: 50, read: 1024
conns created: 1

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the main HTTP client. Safe for concurrent use.

A single Client is designed for requests to one primary host (configured via Config.Host / Config.Port). For multi-host usage, set Request.URL and the client will route to the correct host pool automatically.

func NewClient

func NewClient(config *Config) (*Client, error)

NewClient creates a new HTTP client with the given configuration. Pass nil to use DefaultConfig.

Example
package main

import (
	"fmt"
	"log"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Stop()

	fmt.Println("client created")
}
Output:
client created

func (*Client) AcquireRequest

func (c *Client) AcquireRequest() *Request

AcquireRequest gets a Request from the client's pool.

func (*Client) BuildPreEncodedHeaderPrefix added in v0.1.2

func (c *Client) BuildPreEncodedHeaderPrefix(req *Request, host string, port int, useTLS bool) ([]byte, error)

BuildPreEncodedHeaderPrefix encodes the request line and headers (without Content-Length) for the given host/port/useTLS. The returned slice may be stored on Request.PreEncodedHeaderPrefix to send multiple requests with the same headers without re-encoding. Only the body may change between sends. The request must have Method and Path (or URL) set; host and port should match the target used when sending (e.g. from Config or from URL parsing).

func (*Client) Delete

func (c *Client) Delete(path string, headers []Header) (*Response, error)

Delete performs a DELETE request to path.

func (*Client) Do

func (c *Client) Do(req *Request) (*Response, error)

Do executes an HTTP request using context.Background().

func (*Client) DoReader

func (c *Client) DoReader(ctx context.Context, method, urlOrPath string, bodyReader io.Reader, contentLength int64, headers []Header) (*Response, error)

DoReader executes a request whose body is read from an io.Reader. contentLength must be the exact number of bytes that bodyReader will produce.

func (*Client) DoStreaming

func (c *Client) DoStreaming(ctx context.Context, req *Request) (*StreamingResponse, error)

DoStreaming executes a request and returns a StreamingResponse whose Body is an io.ReadCloser. The caller MUST call StreamingResponse.Close() when done to return the underlying response to the pool.

func (*Client) DoWithContext

func (c *Client) DoWithContext(ctx context.Context, req *Request) (*Response, error)

DoWithContext executes an HTTP request with the given context. If retries are configured, transient failures are retried automatically.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Stop()

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	req := c.AcquireRequest()
	defer c.ReleaseRequest(req)

	req.WithMethod("GET").
		WithURL("https://httpbin.org/get").
		WithHeader("Accept", "application/json")

	resp, err := c.DoWithContext(ctx, req)
	if err != nil {
		log.Fatal(err)
	}
	defer c.ReleaseResponse(resp)
	fmt.Printf("status: %d\n", resp.StatusCode)
}

func (*Client) Get

func (c *Client) Get(path string, headers []Header) (*Response, error)

Get performs a GET request to path using the configured host.

Example
package main

import (
	"fmt"
	"log"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Stop()

	resp, err := c.Get("/get", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer c.ReleaseResponse(resp)
	fmt.Printf("status: %d\n", resp.StatusCode)
}

func (*Client) GetHealthyConnections

func (c *Client) GetHealthyConnections() int

GetHealthyConnections returns the total number of healthy pooled connections.

func (*Client) GetURL

func (c *Client) GetURL(rawURL string, headers []Header) (*Response, error)

GetURL performs a GET request to a full URL.

func (*Client) GracefulStop

func (c *Client) GracefulStop(timeout time.Duration) bool

GracefulStop waits for in-flight requests to complete (up to timeout) before closing all connections. Returns true if all requests drained.

Example
package main

import (
	"fmt"
	"log"
	"time"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}

	drained := c.GracefulStop(5 * time.Second)
	fmt.Printf("drained: %v\n", drained)
}
Output:
drained: true

func (*Client) Head

func (c *Client) Head(path string, headers []Header) (*Response, error)

Head performs a HEAD request to path.

func (*Client) Options

func (c *Client) Options(path string, headers []Header) (*Response, error)

Options performs an OPTIONS request to path.

func (*Client) Patch

func (c *Client) Patch(path string, body []byte, headers []Header) (*Response, error)

Patch performs a PATCH request to path.

func (*Client) Post

func (c *Client) Post(path string, body []byte, headers []Header) (*Response, error)

Post performs a POST request to path with the given body.

Example
package main

import (
	"fmt"
	"log"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Stop()

	resp, err := c.Post("/post", []byte(`{"key":"value"}`), []client.Header{
		{Key: "Content-Type", Value: "application/json"},
	})
	if err != nil {
		log.Fatal(err)
	}
	defer c.ReleaseResponse(resp)
	fmt.Printf("status: %d\n", resp.StatusCode)
}

func (*Client) PostURL

func (c *Client) PostURL(rawURL string, body []byte, headers []Header) (*Response, error)

PostURL performs a POST request to a full URL.

func (*Client) Put

func (c *Client) Put(path string, body []byte, headers []Header) (*Response, error)

Put performs a PUT request to path.

func (*Client) ReleaseRequest

func (c *Client) ReleaseRequest(req *Request)

ReleaseRequest returns a Request to the client's pool.

func (*Client) ReleaseResponse

func (c *Client) ReleaseResponse(resp *Response)

ReleaseResponse returns a Response to the client's pool. Always call this after processing a response to avoid memory leaks.

func (*Client) Start

func (c *Client) Start() error

Start pre-establishes connections to the primary host. The number of connections created is min(n, PoolSize) where n defaults to PoolSize/4 when no argument is given. Returns the number of connections established. Calling Start is optional — connections are created lazily on first request when Start is not called.

func (*Client) StartN

func (c *Client) StartN(n int) error

StartN pre-establishes n connections to the primary host.

func (*Client) Stats

func (c *Client) Stats() ClientStats

Stats returns a snapshot of pool and metrics state.

Example
package main

import (
	"fmt"
	"log"

	client "github.com/muxover/bursthttp"
)

func main() {
	m := client.NewBuiltinMetrics()
	cfg := client.DefaultConfig()
	cfg.Host = "httpbin.org"
	cfg.Port = 443
	cfg.UseTLS = true
	cfg.Metrics = m

	c, err := client.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Stop()

	stats := c.Stats()
	fmt.Printf("healthy: %d, total requests: %d\n", stats.HealthyConnections, stats.Metrics.RequestsTotal)
}
Output:
healthy: 0, total requests: 0

func (*Client) Stop

func (c *Client) Stop()

Stop closes all pooled connections immediately.

type ClientStats

type ClientStats struct {
	HealthyConnections int
	Metrics            MetricsSnapshot
}

ClientStats holds a point-in-time snapshot of client state.

type Compressor

type Compressor struct {
	// contains filtered or unexported fields
}

Compressor manages a pool of gzip writers for request body compression.

func NewCompressor

func NewCompressor(level int) *Compressor

NewCompressor creates a new compressor with the specified compression level.

func (*Compressor) CompressInto

func (c *Compressor) CompressInto(dst []byte, src []byte) ([]byte, error)

CompressInto compresses data into the provided buffer.

type Config

type Config struct {
	Host   string
	Port   int
	UseTLS bool

	PoolSize           int
	MaxRequestsPerConn int
	IdleTimeout        time.Duration

	DialTimeout         time.Duration
	ReadTimeout         time.Duration
	WriteTimeout        time.Duration
	TLSHandshakeTimeout time.Duration

	ReadBufferSize      int
	WriteBufferSize     int
	HeaderBufferSize    int
	HeaderReadChunkSize int
	BodyReadChunkSize   int
	MaxRequestBodySize  int
	MaxResponseBodySize int

	EnableCompression bool
	CompressionLevel  int

	TLSConfig                 *tls.Config
	TLSMinVersion             uint16
	TLSMaxVersion             uint16
	InsecureSkipVerify        bool
	TLSClientSessionCacheSize int

	ProxyURL            string
	ProxyUsername       string
	ProxyPassword       string
	ProxyConnectTimeout time.Duration
	ProxyReadTimeout    time.Duration

	SOCKS5Addr     string // Takes precedence over ProxyURL.
	SOCKS5Username string
	SOCKS5Password string

	KeepAlive bool

	DisableKeepAlive    bool
	MaxIdleConnsPerHost int

	EnablePipelining     bool
	MaxPipelinedRequests int

	MaxRetries      int
	RetryBaseDelay  time.Duration
	RetryMaxDelay   time.Duration
	RetryMultiplier float64
	RetryJitter     bool
	RetryableStatus []int

	EnableDNSCache bool
	DNSCacheTTL    time.Duration
	DNSNegativeTTL time.Duration // how long to cache failed lookups (default 5s)

	// Scheduler: opt-in request scheduler for stable latency under load.
	// When true, DoWithContext routes through per-host worker queues.
	EnableScheduler     bool
	SchedulerWorkers    int // workers per host (default: PoolSize)
	SchedulerQueueDepth int // max queued requests per host (default: workers*4)

	// Connection health scoring: track per-connection latency EWMA and error
	// rate; prefer lower-latency connections during pool selection.
	// Enabled by default.
	EnableHealthScoring bool

	IdleCheckInterval time.Duration

	EnableResponseStreaming bool

	TCPNoDelay         bool
	TCPKeepAlive       bool
	TCPKeepAlivePeriod time.Duration
	TCPFastOpen        bool // Linux only: TCP Fast Open (TFO)
	TCPReusePort       bool // Linux only: SO_REUSEPORT

	// Pipeline auto-tuning: dynamically adjusts pipeline depth per connection
	// based on measured round-trip latency. <10ms → grow; >100ms → shrink.
	EnablePipelineAutoTune bool

	EnableLogging bool

	// Set to a MetricsCollector implementation to receive per-request telemetry.
	// nil disables metrics (default).
	Metrics MetricsCollector
}

Config holds all configuration for the HTTP client. All fields are read-only after initialization for thread safety.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a default configuration optimized for high performance.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	fmt.Printf("host: %s, pool: %d, pipelining: %v\n", cfg.Host, cfg.PoolSize, cfg.EnablePipelining)
}
Output:
host: localhost, pool: 512, pipelining: true

func HighThroughputConfig

func HighThroughputConfig() *Config

HighThroughputConfig returns a config tuned for sustained high RPS. Use this for large-scale workloads (100K+ RPS) with adequate hardware.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.HighThroughputConfig()
	cfg.Host = "api.example.com"
	cfg.Port = 443
	cfg.UseTLS = true

	fmt.Printf("pool size: %d, pipelining: %v\n", cfg.PoolSize, cfg.EnablePipelining)
}
Output:
pool size: 1024, pipelining: true

func ResilientConfig

func ResilientConfig() *Config

ResilientConfig returns a config with retry and resilience features enabled.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.ResilientConfig()
	fmt.Printf("retries: %d, base delay: %v\n", cfg.MaxRetries, cfg.RetryBaseDelay)
}
Output:
retries: 3, base delay: 200ms

func (*Config) BuildTLSConfig

func (c *Config) BuildTLSConfig() *tls.Config

BuildTLSConfig creates a TLS config from the configuration.

func (*Config) Validate

func (c *Config) Validate() error

Validate normalizes and validates the configuration.

type Connection

type Connection struct {
	// contains filtered or unexported fields
}

Connection owns a single TCP/TLS connection with optional pipelining.

func NewConnection

func NewConnection(id int, host string, port int, config *Config, dialer *Dialer, tlsConfig *TLSConfig, compressor *Compressor) *Connection

NewConnection creates a Connection. TCP is not established until first use.

func (*Connection) CanAcceptRequest

func (c *Connection) CanAcceptRequest() bool

CanAcceptRequest returns true when the connection can take another request.

func (*Connection) Do

func (c *Connection) Do(req *Request) (*Response, error)

Do executes a request on this connection.

func (*Connection) HealthScore added in v0.1.3

func (c *Connection) HealthScore() int32

HealthScore returns the current health score (0–100, higher is better). Returns 100 for new connections with no data yet.

func (*Connection) IsHealthy

func (c *Connection) IsHealthy() bool

IsHealthy returns true if the connection is alive and not stopped.

func (*Connection) Stop

func (c *Connection) Stop()

Stop permanently stops the connection.

type DNSCache

type DNSCache struct {
	// contains filtered or unexported fields
}

DNSCache is a thread-safe, TTL-based DNS resolution cache with async refresh, in-flight deduplication, round-robin IP selection, and negative caching.

func NewDNSCache

func NewDNSCache(ttl time.Duration, negativeTTL time.Duration) *DNSCache

NewDNSCache creates a new DNS cache with the given TTL and starts background prefetch and janitor goroutines.

Example
package main

import (
	"fmt"
	"log"
	"time"

	client "github.com/muxover/bursthttp"
)

func main() {
	cache := client.NewDNSCache(5*time.Minute, 5*time.Second)
	defer cache.Stop()

	addrs, err := cache.LookupHost("localhost")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("resolved: %v\n", len(addrs) > 0)
}
Output:
resolved: true

func (*DNSCache) Clear

func (c *DNSCache) Clear()

Clear removes all cached entries.

func (*DNSCache) Invalidate

func (c *DNSCache) Invalidate(host string)

Invalidate removes a host from the cache.

func (*DNSCache) LookupHost

func (c *DNSCache) LookupHost(host string) ([]string, error)

LookupHost resolves a hostname to an IP address using the cache. Multiple concurrent misses for the same host share one lookup (singleflight). Returns a single IP selected via round-robin when multiple IPs are cached.

func (*DNSCache) Refresh

func (c *DNSCache) Refresh(host string) ([]string, error)

Refresh forces a fresh DNS lookup for the given host, updating the cache.

func (*DNSCache) Stop

func (c *DNSCache) Stop()

Stop shuts down the background goroutines.

type DetailedError

type DetailedError struct {
	Type    ErrorType
	Message string
	Err     error
	Context map[string]interface{}
}

DetailedError wraps an error with type and context for detailed logging.

func (*DetailedError) Error

func (e *DetailedError) Error() string

Error implements the error interface.

func (*DetailedError) Unwrap

func (e *DetailedError) Unwrap() error

Unwrap returns the underlying error.

type Dialer

type Dialer struct {
	// contains filtered or unexported fields
}

Dialer handles TCP connection establishment with optimised socket settings.

func NewDialer

func NewDialer(config *Config) (*Dialer, error)

NewDialer creates a new Dialer from configuration.

func (*Dialer) Dial

func (d *Dialer) Dial() (net.Conn, error)

Dial establishes a connection to the given address ("host:port"). Falls back to config Host/Port when address is empty.

func (*Dialer) DialAddr

func (d *Dialer) DialAddr(host string, port int) (net.Conn, error)

DialAddr establishes a connection to host:port. When host is empty, d.config.Host is used; when port is 0, d.config.Port is used.

func (*Dialer) DialForward added in v0.1.1

func (d *Dialer) DialForward() (net.Conn, error)

DialForward connects to the proxy's TCP address without issuing a CONNECT request, then applies the same socket options as DialAddr. Used when IsForwardProxy returns true.

func (*Dialer) IsForwardProxy added in v0.1.1

func (d *Dialer) IsForwardProxy(useTLS bool) bool

IsForwardProxy reports whether HTTP requests to non-TLS targets should be sent via forward-proxy mode (absolute URI + Proxy-Authorization), rather than through an HTTP CONNECT tunnel.

func (*Dialer) ProxyAuthHeader added in v0.1.1

func (d *Dialer) ProxyAuthHeader() []byte

ProxyAuthHeader returns the pre-encoded "Proxy-Authorization: Basic …\r\n" header bytes, or nil when no proxy credentials are configured.

func (*Dialer) Stop

func (d *Dialer) Stop()

Stop cleans up dialer resources (DNS cache).

type ErrorType

type ErrorType string

ErrorType represents the category of error for logging and handling.

const (
	ErrorTypeNetwork    ErrorType = "network"
	ErrorTypeTimeout    ErrorType = "timeout"
	ErrorTypeProtocol   ErrorType = "protocol"
	ErrorTypeTLS        ErrorType = "tls"
	ErrorTypeProxy      ErrorType = "proxy"
	ErrorTypeValidation ErrorType = "validation"
	ErrorTypeInternal   ErrorType = "internal"
)
type Header struct {
	Key   string
	Value string
}

Header is a single HTTP header key-value pair.

type HostPool

type HostPool struct {
	// contains filtered or unexported fields
}

HostPool manages connections for a single scheme+host+port key. connections is updated with atomic.Pointer for lock-free get path.

type MetricsCollector

type MetricsCollector interface {
	// RecordRequest is called when a request starts. Returns a timestamp
	// that should be passed to RecordResponse for latency tracking.
	RecordRequest(method, host string) time.Time

	// RecordResponse is called after every completed request.
	// statusCode is 0 if the request failed before a response was received.
	// err is non-nil when the request failed.
	// start is the timestamp returned by RecordRequest.
	// bytesWritten and bytesRead are wire-level byte counts.
	RecordResponse(method, host string, statusCode int, err error, start time.Time, bytesWritten, bytesRead int64)

	// RecordPoolEvent is called for connection pool events.
	RecordPoolEvent(event PoolEvent, host string)

	// Snapshot returns a point-in-time copy of collected metrics.
	Snapshot() MetricsSnapshot
}

MetricsCollector is the interface for receiving request/response events. Implement it and set Config.Metrics to plug in any metrics backend (Prometheus, statsd, in-memory, etc.).

All methods must be safe for concurrent use.

type MetricsSnapshot

type MetricsSnapshot struct {
	RequestsTotal int64
	RequestsOK    int64
	RequestsError int64
	Requests4xx   int64
	Requests5xx   int64
	Requests1xx   int64
	Requests3xx   int64
	RetriesTotal  int64

	BytesWritten int64
	BytesRead    int64

	LatencyP50 time.Duration
	LatencyP95 time.Duration
	LatencyP99 time.Duration
	LatencyAvg time.Duration
	LatencyMin time.Duration
	LatencyMax time.Duration

	ConnsCreated int64
	ConnsClosed  int64
	ConnsReused  int64
	ConnsFailed  int64
}

MetricsSnapshot is a point-in-time copy of collected metric values.

type MultipartBuilder

type MultipartBuilder struct {
	// contains filtered or unexported fields
}

MultipartBuilder constructs a multipart/form-data body incrementally. Use NewMultipartBuilder, add fields/files, then call Finish to get the body bytes and Content-Type header value.

Example
package main

import (
	"fmt"
	"log"

	client "github.com/muxover/bursthttp"
)

func main() {
	mb := client.NewMultipartBuilder()
	mb.AddField("username", "alice")
	mb.AddField("email", "alice@example.com")
	mb.AddFileFromBytes("avatar", "avatar.png", []byte("fake-png-data"))

	body, contentType, err := mb.Finish()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("has body: %v, has boundary: %v\n", len(body) > 0, len(contentType) > 0)
}
Output:
has body: true, has boundary: true

func NewMultipartBuilder

func NewMultipartBuilder() *MultipartBuilder

NewMultipartBuilder creates a new multipart body builder.

func (*MultipartBuilder) AddField

func (mb *MultipartBuilder) AddField(name, value string) error

AddField adds a text form field.

func (*MultipartBuilder) AddFileFromBytes

func (mb *MultipartBuilder) AddFileFromBytes(fieldName, fileName string, data []byte) error

AddFileFromBytes adds a file field from an in-memory byte slice.

func (*MultipartBuilder) AddFileFromPath

func (mb *MultipartBuilder) AddFileFromPath(fieldName, filePath string) error

AddFileFromPath adds a file field by reading from the filesystem.

func (*MultipartBuilder) AddFileFromReader

func (mb *MultipartBuilder) AddFileFromReader(fieldName, fileName string, reader io.Reader) error

AddFileFromReader adds a file field by reading from an io.Reader.

func (*MultipartBuilder) ContentType

func (mb *MultipartBuilder) ContentType() string

ContentType returns the Content-Type header value including the boundary. Must be called after Finish (or at any point for the current boundary).

func (*MultipartBuilder) Finish

func (mb *MultipartBuilder) Finish() (body []byte, contentType string, err error)

Finish closes the multipart writer (writes the trailing boundary) and returns the complete body bytes and Content-Type header value.

type PendingRequest

type PendingRequest struct {
	// contains filtered or unexported fields
}

PendingRequest represents a request queued for a pipelined response. It is added to pendingReqs only AFTER the request has been written to the wire.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool manages per-host connection pools. Host pool lookup and connection list access are lock-free (sync.Map + atomic.Pointer for the connection slice).

func NewPool

func NewPool(config *Config, dialer *Dialer, tlsConfig *TLSConfig, compressor *Compressor) *Pool

NewPool creates a new connection pool.

func (*Pool) GetConnection

func (p *Pool) GetConnection(key string, useTLS bool) *Connection

GetConnection returns an available connection for the given pool key. key is "scheme://host:port" (e.g. "https://api.example.com:443"). useTLS controls whether new connections use TLS.

func (*Pool) GetHealthyConnections

func (p *Pool) GetHealthyConnections() int

GetHealthyConnections returns the total healthy connection count across all pools.

func (*Pool) GracefulStop

func (p *Pool) GracefulStop(timeout time.Duration) bool

GracefulStop waits for in-flight requests to complete (up to timeout) before closing all connections. Returns true if all requests drained cleanly.

func (*Pool) Stop

func (p *Pool) Stop()

Stop closes every connection in every host pool.

func (*Pool) WarmUp

func (p *Pool) WarmUp(key string, useTLS bool, n int) int

WarmUp pre-establishes connections for the primary host. n is the number of connections to create (capped at PoolSize).

type PoolEvent

type PoolEvent int

PoolEvent represents a connection pool lifecycle event.

const (
	PoolEventConnCreated PoolEvent = iota
	PoolEventConnClosed
	PoolEventConnReused
	PoolEventConnFailed
)

type ProxyDialer

type ProxyDialer struct {
	// contains filtered or unexported fields
}

ProxyDialer handles HTTP CONNECT proxy connections with authentication. Optimized for zero-allocation and minimal syscalls.

func NewProxyDialer

func NewProxyDialer(config *Config) (*ProxyDialer, error)

NewProxyDialer creates a new proxy dialer from configuration.

func (*ProxyDialer) Dial

func (p *ProxyDialer) Dial(host string, port int) (net.Conn, error)

Dial establishes a connection through the proxy using HTTP CONNECT. Each CONNECT tunnel is bound to a single target; the main pool handles reuse.

func (*ProxyDialer) DialForward added in v0.1.1

func (p *ProxyDialer) DialForward() (net.Conn, error)

DialForward connects to the proxy over plain TCP without issuing a CONNECT request. Used for HTTP (non-TLS) targets where the proxy acts as a forward proxy: the client sends the absolute-form request directly to the proxy TCP socket and the proxy forwards it to the origin.

type Request

type Request struct {
	// Method is the HTTP verb (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS).
	Method string

	// URL is a full URL e.g. "https://api.example.com/v1/users".
	// When set, Host/Port/TLS are derived from it; Path is ignored.
	URL string

	// Path is the request path used when URL is empty (e.g. "/api/v1/users").
	// Deprecated in favour of URL for multi-host clients.
	Path string

	// Body is the raw request body.
	Body []byte

	// Compressed, if true, gzip-compresses Body before sending
	// (requires Compressor configured in Client).
	Compressed bool

	// Per-request timeout overrides (0 = use client config).
	ReadTimeout  time.Duration
	WriteTimeout time.Duration

	// ExpectContinue, when true, sends "Expect: 100-continue" and waits
	// for a 100 response before transmitting the body.
	ExpectContinue bool

	// PreEncodedHeaderPrefix, when non-nil, is the pre-encoded request header
	// (request line + all headers) up to but not including "Content-Length: N\r\n\r\n".
	// The connection will append Content-Length and body. Build via BuildPreEncodedHeaderPrefix.
	PreEncodedHeaderPrefix []byte
	// contains filtered or unexported fields
}

Request represents an HTTP request with pre-allocated buffers. Acquire via Client.AcquireRequest() or the package-level AcquireRequest(). Release after Do() returns via Client.ReleaseRequest() or ReleaseRequest().

Example (Fluent)
package main

import (
	"context"
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	req := client.AcquireRequest()
	defer client.ReleaseRequest(req)

	req.WithMethod("POST").
		WithPath("/api/v1/data").
		WithBody([]byte(`{"key":"value"}`)).
		WithHeader("Content-Type", "application/json").
		WithContext(context.Background())

	fmt.Printf("method: %s, path: %s\n", req.Method, req.Path)
}
Output:
method: POST, path: /api/v1/data

func AcquireRequest

func AcquireRequest() *Request

AcquireRequest gets a Request from the global pool.

func BuildMultipartRequest

func BuildMultipartRequest(client *Client, method, urlOrPath string, fields map[string]string, files map[string][]byte) (*Request, error)

BuildMultipartRequest is a convenience that creates a Request with a multipart body from field and file data.

func (*Request) Context

func (r *Request) Context() context.Context

Context returns the request's context (context.Background() if nil).

func (*Request) Reset

func (r *Request) Reset()

Reset clears the request for reuse, preserving underlying buffer capacity.

func (*Request) SetBody

func (r *Request) SetBody(body []byte)

SetBody sets the request body.

func (*Request) SetContext

func (r *Request) SetContext(ctx context.Context)

SetContext sets the context for the request.

func (*Request) SetHeader

func (r *Request) SetHeader(key, value string) bool

SetHeader appends a header in wire format ("Key: Value\r\n") to the internal buffer. Returns false if key/value contain CR or LF (header injection protection) or if the buffer cannot grow beyond 1 MB.

func (*Request) WithBody

func (r *Request) WithBody(body []byte) *Request

WithBody sets the request body and returns r for chaining.

func (*Request) WithCompression

func (r *Request) WithCompression() *Request

WithCompression enables gzip compression of the request body.

func (*Request) WithContext

func (r *Request) WithContext(ctx context.Context) *Request

WithContext sets the cancellation context and returns r for chaining.

func (*Request) WithExpectContinue

func (r *Request) WithExpectContinue() *Request

WithExpectContinue enables the Expect: 100-continue protocol. The client sends headers first, waits for a 100 response, then sends the body.

func (*Request) WithHeader

func (r *Request) WithHeader(key, value string) *Request

WithHeader adds a header in wire format and returns r for chaining. Returns r unchanged if the buffer is full (grows automatically up to 1 MB).

func (*Request) WithMethod

func (r *Request) WithMethod(method string) *Request

WithMethod sets the HTTP method and returns r for chaining.

func (*Request) WithPath

func (r *Request) WithPath(path string) *Request

WithPath sets the request path (used when URL is empty) and returns r.

func (*Request) WithReadTimeout

func (r *Request) WithReadTimeout(d time.Duration) *Request

WithReadTimeout overrides the client read timeout for this request.

func (*Request) WithURL

func (r *Request) WithURL(rawURL string) *Request

WithURL sets the full URL and returns r for chaining. Example: req.WithURL("https://api.example.com/v1/items")

func (*Request) WithWriteTimeout

func (r *Request) WithWriteTimeout(d time.Duration) *Request

WithWriteTimeout overrides the client write timeout for this request.

type Response

type Response struct {
	StatusCode    int
	ContentLength int
	Body          []byte
	Headers       []Header
	// contains filtered or unexported fields
}

Response represents an HTTP response with pre-allocated body buffer.

func AcquireResponse

func AcquireResponse() *Response

AcquireResponse gets a response from the pool.

func AcquireResponseWithMaxSize

func AcquireResponseWithMaxSize(maxSize int) *Response

AcquireResponseWithMaxSize gets a response from the pool with a maximum size limit. This allows per-client configuration while maintaining pool efficiency.

func (*Response) HasHeader

func (r *Response) HasHeader(key string) bool

HasHeader reports whether the response contains the named header (case-insensitive).

func (*Response) Header

func (r *Response) Header(key string) string

Header returns the first value for the given header key (case-insensitive). Returns empty string if the header is not present.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	resp := &client.Response{
		StatusCode: 200,
		Headers: []client.Header{
			{Key: "Content-Type", Value: "application/json"},
			{Key: "X-Request-Id", Value: "abc123"},
		},
	}
	fmt.Println(resp.Header("content-type"))
	fmt.Println(resp.HasHeader("X-Request-Id"))
}
Output:
application/json
true

func (*Response) HeaderBytes added in v0.1.2

func (r *Response) HeaderBytes(key string) []byte

HeaderBytes returns the first value for the given header key as a slice into the response's raw header buffer (zero-copy). The slice is valid only until ReleaseResponse is called. Returns nil if the header is not present. Case-insensitive header name match.

func (*Response) HeaderValues

func (r *Response) HeaderValues(key string) []string

HeaderValues returns all values for the given header key (case-insensitive). Returns nil if the header is not present.

Example
package main

import (
	"fmt"

	client "github.com/muxover/bursthttp"
)

func main() {
	resp := &client.Response{
		StatusCode: 200,
		Headers: []client.Header{
			{Key: "Set-Cookie", Value: "a=1"},
			{Key: "Set-Cookie", Value: "b=2"},
		},
	}
	for _, v := range resp.HeaderValues("Set-Cookie") {
		fmt.Println(v)
	}
}
Output:
a=1
b=2

func (*Response) Reset

func (r *Response) Reset()

Reset clears the response for reuse.

type ResponseReader

type ResponseReader struct {
	// contains filtered or unexported fields
}

ResponseReader is a per-connection goroutine that reads responses in FIFO order. It uses a persistent bufio.Reader to preserve any leftover bytes that arrived in the same TCP segment as a previous response (essential for pipelining).

type Retryer

type Retryer struct {
	// contains filtered or unexported fields
}

Retryer executes a request with configurable retry logic. It is created from the client's Config and reused across requests.

func NewRetryer

func NewRetryer(config *Config) *Retryer

NewRetryer creates a Retryer from configuration. Returns nil when retries are disabled (MaxRetries == 0).

Example
package main

import (
	"fmt"
	"time"

	client "github.com/muxover/bursthttp"
)

func main() {
	cfg := client.DefaultConfig()
	cfg.MaxRetries = 3
	cfg.RetryBaseDelay = 100 * time.Millisecond
	cfg.RetryMaxDelay = 5 * time.Second
	cfg.RetryMultiplier = 2.0
	cfg.RetryJitter = true

	r := client.NewRetryer(cfg)
	if r != nil {
		fmt.Printf("backoff attempt 0: %v\n", r.Backoff(0) > 0)
		fmt.Printf("backoff attempt 2: %v\n", r.Backoff(2) > 0)
	}
}
Output:
backoff attempt 0: true
backoff attempt 2: true

func (*Retryer) Backoff

func (r *Retryer) Backoff(attempt int) time.Duration

Backoff returns the duration to wait before the given retry attempt. Uses exponential backoff with optional jitter.

func (*Retryer) ShouldRetry

func (r *Retryer) ShouldRetry(attempt int, resp *Response, err error) bool

ShouldRetry reports whether the request should be retried based on the response status code or error. attempt is 0-indexed (first retry = 0).

func (*Retryer) Wait

func (r *Retryer) Wait(ctx context.Context, attempt int) error

Wait sleeps for the backoff duration, returning early if ctx is cancelled. Returns ctx.Err() if the context fires before the backoff elapses.

type SOCKS5Dialer

type SOCKS5Dialer struct {
	// contains filtered or unexported fields
}

SOCKS5Dialer handles connections through a SOCKS5 proxy.

func NewSOCKS5Dialer

func NewSOCKS5Dialer(config *Config) (*SOCKS5Dialer, error)

NewSOCKS5Dialer creates a SOCKS5 dialer from configuration.

func (*SOCKS5Dialer) Dial

func (d *SOCKS5Dialer) Dial(host string, port int) (net.Conn, error)

Dial connects to the target host:port through the SOCKS5 proxy.

type Scheduler added in v0.1.3

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler routes requests through per-host queues processed by a bounded worker pool. This replaces the spin-wait in GetConnection with a proper blocking queue, giving stable latency under overload and eliminating busy-wait CPU overhead when all connections are busy.

func NewScheduler added in v0.1.3

func NewScheduler(client *Client, workers, queueCap int) *Scheduler

NewScheduler creates a Scheduler backed by the given client. workers is the number of worker goroutines per host (default: PoolSize). queueCap is the max queued requests per host before Do blocks (default: workers*4).

func (*Scheduler) Do added in v0.1.3

func (s *Scheduler) Do(ctx context.Context, req *Request, poolKey string, useTLS bool) (*Response, error)

Do submits req to the per-host scheduler and blocks until a response or error. poolKey is "scheme://host:port"; useTLS must match the scheme.

func (*Scheduler) Stop added in v0.1.3

func (s *Scheduler) Stop()

Stop drains the queues and shuts down all worker goroutines.

type StreamingResponse

type StreamingResponse struct {
	StatusCode    int
	ContentLength int
	Headers       []Header
	Body          io.ReadCloser
	// contains filtered or unexported fields
}

StreamingResponse wraps a Response with an io.ReadCloser for the body. Use Client.DoStreaming to obtain one. The caller MUST call Close() when done.

func (*StreamingResponse) Close

func (sr *StreamingResponse) Close() error

Close releases the underlying response back to the pool. Must be called after the body has been fully consumed or abandoned.

func (*StreamingResponse) HasHeader

func (sr *StreamingResponse) HasHeader(key string) bool

HasHeader reports whether the streaming response contains the named header.

func (*StreamingResponse) Header

func (sr *StreamingResponse) Header(key string) string

Header returns the first value for the given header key (case-insensitive).

type TLSConfig

type TLSConfig struct {
	// contains filtered or unexported fields
}

TLSConfig wraps tls.Config with optimized session caching and connection management.

func NewTLSConfig

func NewTLSConfig(config *Config) *TLSConfig

NewTLSConfig creates a new TLS configuration with session caching enabled.

func (*TLSConfig) WrapConnection

func (t *TLSConfig) WrapConnection(conn net.Conn) (net.Conn, error)

WrapConnection performs a TLS handshake over an existing connection. Uses session caching for faster reconnection.

Directories

Path Synopsis
examples
advanced command
Advanced bursthttp usage: high-throughput, retry, metrics, streaming, multipart.
Advanced bursthttp usage: high-throughput, retry, metrics, streaming, multipart.
basic command
Basic usage of bursthttp.
Basic usage of bursthttp.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL