Documentation
¶
Index ¶
Constants ¶
const ShadowHeader = "X-Mroki-Mode"
ShadowHeader is the fixed header added to requests forwarded to the shadow service so downstream systems can distinguish shadow traffic from live traffic. The name is intentionally not configurable so consumers can rely on a stable convention. The live request path is never modified.
Variables ¶
This section is empty.
Functions ¶
func NewProxyResponseDiffer ¶
Types ¶
type CallbackFunc ¶
type CallbackFunc func(req ProxyRequest, live, shadow ProxyResponse) error
type CheckFunc ¶
CheckFunc returns true if the request should be proxied to shadow
func MaxBodySizeCheck ¶
MaxBodySizeCheck skips shadow for large or chunked bodies maxBytes <= 0 means unlimited (always returns true)
func SamplingRateCheck ¶
func SamplingRateCheck(rate *SamplingRate) CheckFunc
SamplingRateCheck skips shadow based on sampling probability. rate == nil means always sample (always returns true). rate=1.0 and rate=0.0 use fast paths without RNG computation.
type Option ¶
type Option func(*Proxy)
func WithCallbackFn ¶
func WithCallbackFn(fn CallbackFunc) Option
func WithHTTPClient ¶
WithHTTPClient allows setting a custom HTTP client
func WithLiveTimeout ¶
WithLiveTimeout sets the timeout for live requests
func WithLogger ¶
WithLogger sets the logger for proxy operations
func WithShadowTimeout ¶
WithShadowTimeout sets the timeout for shadow requests
func WithShouldProxyToShadow ¶
WithShouldProxyToShadow adds check functions to determine if shadow should be proxied Multiple checks can be provided - all must return true (AND logic) Can be called multiple times to add more checks
type Proxy ¶
func (*Proxy) ServeHTTP ¶
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the http.Handler interface for proxying requests.
Request Flow:
- Reads request body (needed to replay to both services)
- Launches live request with client context + timeout
- Launches shadow request (if sampled) with independent context + timeout
- Waits for live response and returns to client immediately
- Invokes callback with raw responses in background goroutine
Context Handling:
- Live requests inherit the client's request context (r.Context()) This means if the client disconnects, live request is cancelled
- Shadow requests use context.Background() as parent context This makes shadow independent of client connection state, ensuring complete response data collection even if client disconnects
- Both contexts have their own timeout values for safety
Timeouts:
- liveTimeout: Controls how long to wait for live service (blocks client)
- shadowTimeout: Controls how long shadow service can run (doesn't block client)
- Shadow timeout can be longer since it doesn't impact user experience
type ProxyRequest ¶
type ProxyRequest struct {
Method string
Path string
RawQuery string
Headers http.Header
Body []byte
}
ProxyRequest represents the original HTTP request being proxied
type ProxyResponse ¶
type SamplingRate ¶
type SamplingRate float64
func NewSamplingRate ¶
func NewSamplingRate(rate float64) (*SamplingRate, error)
func (SamplingRate) IsZero ¶
func (s SamplingRate) IsZero() bool
IsZero checks if the sampling rate is zero.
func (SamplingRate) Sample ¶
func (s SamplingRate) Sample() bool
Sample decides whether to sample based on the sampling rate. It returns true if the request should be sampled, false otherwise. Fast paths: rate=1.0 always returns true, rate=0.0 always returns false (no RNG).
func (SamplingRate) String ¶
func (s SamplingRate) String() string
String returns the sampling rate as a formatted string.