- Deduplicate sentinel errors: httpx.ErrNoHealthy, ErrCircuitOpen, and ErrRetryExhausted are now aliases to the canonical sub-package values so errors.Is works across package boundaries - Retry transport returns ErrRetryExhausted only when all attempts are actually exhausted, not on early policy exit - Balancer: pre-parse endpoint URLs at construction, replace req.Clone with cheap shallow struct copy to avoid per-request allocations - Circuit breaker: Load before LoadOrStore to avoid allocating a Breaker on every request for known hosts - Health checker: drain response body before close for connection reuse, probe endpoints concurrently, run initial probe synchronously in Start - Client: add Close() to shut down health checker goroutine, propagate URL resolution errors instead of silently discarding them - MockClock: fix lock ordering in Reset (clock.mu before t.mu), fix timer slice compaction to avoid backing-array aliasing, extract fireExpired to deduplicate Advance/Set
50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
package httpx
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"git.codelab.vc/pkg/httpx/balancer"
|
|
"git.codelab.vc/pkg/httpx/circuitbreaker"
|
|
"git.codelab.vc/pkg/httpx/retry"
|
|
)
|
|
|
|
// Sentinel errors returned by httpx components.
|
|
// These are aliases for the canonical errors defined in sub-packages,
|
|
// so that errors.Is works regardless of which import the caller uses.
|
|
var (
|
|
ErrRetryExhausted = retry.ErrRetryExhausted
|
|
ErrCircuitOpen = circuitbreaker.ErrCircuitOpen
|
|
ErrNoHealthy = balancer.ErrNoHealthy
|
|
)
|
|
|
|
// Error provides structured error information for failed HTTP operations.
|
|
type Error struct {
|
|
// Op is the operation that failed (e.g. "Get", "Do").
|
|
Op string
|
|
// URL is the originally-requested URL.
|
|
URL string
|
|
// Endpoint is the resolved endpoint URL (after balancing).
|
|
Endpoint string
|
|
// StatusCode is the HTTP status code, if a response was received.
|
|
StatusCode int
|
|
// Retries is the number of retry attempts made.
|
|
Retries int
|
|
// Err is the underlying error.
|
|
Err error
|
|
}
|
|
|
|
func (e *Error) Error() string {
|
|
if e.Endpoint != "" && e.Endpoint != e.URL {
|
|
return fmt.Sprintf("httpx: %s %s (endpoint %s): %v", e.Op, e.URL, e.Endpoint, e.Err)
|
|
}
|
|
return fmt.Sprintf("httpx: %s %s: %v", e.Op, e.URL, e.Err)
|
|
}
|
|
|
|
func (e *Error) Unwrap() error { return e.Err }
|
|
|
|
// ErrorMapper maps an HTTP response to an error. If the response is
|
|
// acceptable, the mapper should return nil. Used by Client to convert
|
|
// non-successful HTTP responses into Go errors.
|
|
type ErrorMapper func(resp *http.Response) error
|