Documentation
¶
Index ¶
- Variables
- func NewClient(serviceType string, opts ...Option) (*http.Client, func(), error)
- type AuthAttacher
- type BearerAttacher
- type Dialer
- type Discovery
- type NoAuthAttacher
- type Option
- func WithAuthAttacher(a AuthAttacher) Option
- func WithBearer(b string) Option
- func WithBrowseInterval(d time.Duration) Option
- func WithClientID(id string) Option
- func WithDialer(d Dialer) Option
- func WithDiscoverTimeout(d time.Duration) Option
- func WithDiscovery(d Discovery) Option
- func WithHTTPTimeout(d time.Duration) Option
- func WithLocalTrust() Option
- func WithMinPeers(n int) Option
- func WithPicker(p Picker) Option
- type Options
- type Peer
- type Picker
- type RoundRobinPicker
- type ZAPHTTPDialer
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoPeers is returned by Picker when discovery has no live // peers for the service. ErrNoPeers = errors.New("clienthttp: no peers discovered") )
Sentinel errors. Callers branch via errors.Is.
Functions ¶
Types ¶
type AuthAttacher ¶
type AuthAttacher interface {
// Attach mutates req in place. A non-nil error aborts the
// RoundTrip — surface this rather than silently dropping auth.
Attach(req *http.Request, peer Peer) error
}
AuthAttacher injects per-call authentication onto outgoing requests. It runs after Picker selects the peer but before the RoundTrip itself, so the chosen peer can influence which credential gets attached (e.g. local-trust skips the bearer, cross-cluster uses a different key).
Implementations MUST NOT block — set headers and return. Network I/O belongs in the Dialer's RoundTripper, not the AuthAttacher.
type BearerAttacher ¶
type BearerAttacher struct {
Bearer string
}
BearerAttacher attaches a bearer token. Empty Bearer is a no-op (the bearer field is the no-trust-needed signal).
type Dialer ¶
type Dialer interface {
// Dial returns a RoundTripper speaking to peer.Address. The
// returned RoundTripper is goroutine-safe and reusable.
Dial(ctx context.Context, peer Peer) (http.RoundTripper, error)
}
Dialer returns an http.RoundTripper that talks to one peer.
The returned RoundTripper SHOULD be cached per address so the underlying transport's connection pool gets reused. clienthttp's default transport handles caching internally; custom Dialers MAY cache or return fresh RoundTrippers as appropriate.
type Discovery ¶
type Discovery interface {
// Peers returns the current peer snapshot. Order is implementation-
// defined; consumers MUST NOT mutate the returned slice.
Peers() []Peer
// PeerCount returns len(Peers()) cheaply.
PeerCount() int
// ServiceType reports the service the Discovery is browsing.
ServiceType() string
// Start begins the discovery loop. Calling Start twice on the same
// Discovery is a programmer error.
Start() error
// Stop releases all resources. Idempotent.
Stop()
}
Discovery is the peer-enumeration contract.
Implementations MUST be goroutine-safe; clienthttp may call Peers() from every in-flight RoundTrip and from background reconciliation. PeerCount() is a hot-path helper for waitForPeers and similar gating logic; it MUST return cheap snapshot semantics, not require a network probe.
type NoAuthAttacher ¶
type NoAuthAttacher struct{}
NoAuthAttacher is the local-trust attacher: trust comes from the mDNS-bounded ZAP TLS scope, not from a header. Calling code can still pass per-call headers; this attacher just does nothing.
type Option ¶
type Option func(*Options)
Option is the functional-option constructor knob.
func WithAuthAttacher ¶
func WithAuthAttacher(a AuthAttacher) Option
WithAuthAttacher pins a custom AuthAttacher (mTLS-derived identity, signed-request headers, etc.). Overrides WithBearer and WithLocalTrust.
func WithBearer ¶
WithBearer attaches `Authorization: Bearer <b>` on every call. Mutually exclusive with WithLocalTrust / WithAuthAttacher.
func WithBrowseInterval ¶
WithBrowseInterval sets the mDNS browse interval (default backend).
func WithClientID ¶
WithClientID names this caller in its mDNS announcement.
func WithDialer ¶
WithDialer overrides the per-peer RoundTripper factory.
func WithDiscoverTimeout ¶
WithDiscoverTimeout caps the initial peer-discovery wait.
func WithDiscovery ¶
WithDiscovery overrides the peer-discovery backend. Useful for tests + non-mDNS environments (Consul, etcd, static).
func WithHTTPTimeout ¶
WithHTTPTimeout caps each outbound request's total time.
func WithLocalTrust ¶
func WithLocalTrust() Option
WithLocalTrust signals that this client runs inside the trusted ZAP mesh — the bearer attach is skipped. Use only when:
- The peer is reachable only on the cluster-private network (k8s pod network, not the public internet).
- Discovery is mDNS bounded to that network (multicast scope).
- ZAP TLS verifies peers against the cluster CA so even an attacker on the same segment cannot impersonate a service.
Cross-cluster + ingress callers MUST NOT use this; they require an explicit bearer attached via WithBearer or a custom AuthAttacher.
func WithMinPeers ¶
WithMinPeers waits for at least N peers before NewClient returns.
func WithPicker ¶
WithPicker overrides the per-RoundTrip peer selector.
type Options ¶
type Options struct {
// ClientID identifies this caller in mDNS announcements. Empty
// generates a small uuid-like suffix. The id has no security
// meaning — auth lives in AuthAttacher.
ClientID string
// Bearer is shorthand for the default BearerAttacher. Mutually
// exclusive with WithLocalTrust / WithAuthAttacher; later option
// wins.
Bearer string
// MinPeers blocks NewClient until at least N peers are discovered
// (or DiscoverTimeout elapses). Default 1.
MinPeers int
// DiscoverTimeout caps the initial peer-discovery wait. Default
// 10 * BrowseInterval.
DiscoverTimeout time.Duration
// BrowseInterval is how often mDNS re-browses for peers. Default
// 5 seconds.
BrowseInterval time.Duration
// HTTPTimeout caps each outbound request. Default 30 seconds.
HTTPTimeout time.Duration
// Pluggable wiring. nil means "use default for this concern."
Discovery Discovery
Picker Picker
Dialer Dialer
Auth AuthAttacher
}
Options configure NewClient. Construct via WithX options; do not instantiate directly.
type Peer ¶
type Peer struct {
NodeID string
ServiceType string
Address string
Metadata map[string]string
LastSeen time.Time
}
Peer is the discovery view of one reachable instance of a service.
Address is the dial target ("host:port"). Metadata carries optional hints (zone, version, capabilities) — implementations choose what to surface. NodeID uniquely identifies the peer within ServiceType across discovery cycles so callers can correlate sticky-routing decisions.
type Picker ¶
type Picker interface {
// Pick returns the chosen peer. ErrNoPeers if peers is empty.
Pick(peers []Peer) (Peer, error)
}
Picker selects one peer from a Discovery snapshot.
Pick is called once per RoundTrip; implementations MUST be cheap (sub-microsecond) and goroutine-safe.
type RoundRobinPicker ¶
type RoundRobinPicker struct {
// contains filtered or unexported fields
}
RoundRobinPicker rotates through peers in registration order. Zero-value is ready to use; safe for concurrent Pick calls.
type ZAPHTTPDialer ¶
type ZAPHTTPDialer struct {
// contains filtered or unexported fields
}
ZAPHTTPDialer returns RoundTrippers speaking ZAP-HTTP. Goroutine- safe; one instance can serve many concurrent peers via the per-address cache.
func NewZAPHTTPDialer ¶
func NewZAPHTTPDialer() *ZAPHTTPDialer
NewZAPHTTPDialer constructs a ZAPHTTPDialer with an empty cache.
func (*ZAPHTTPDialer) Dial ¶
func (d *ZAPHTTPDialer) Dial(_ context.Context, peer Peer) (http.RoundTripper, error)
Dial returns the cached zaphttp.Transport for peer.Address, constructing one on first use.