Introduce the core building blocks for the httpx library: - middleware.Middleware type and Chain() composer - Error struct with sentinel errors (ErrRetryExhausted, ErrCircuitOpen, ErrNoHealthy) - internal/clock package with Clock interface and MockClock for deterministic testing
45 lines
1.3 KiB
Go
45 lines
1.3 KiB
Go
package httpx
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
)
|
|
|
|
// Sentinel errors returned by httpx components.
|
|
var (
|
|
ErrRetryExhausted = errors.New("httpx: all retry attempts exhausted")
|
|
ErrCircuitOpen = errors.New("httpx: circuit breaker is open")
|
|
ErrNoHealthy = errors.New("httpx: no healthy endpoints available")
|
|
)
|
|
|
|
// 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
|