Documentation
¶
Overview ¶
Package exec implements HTTP request execution for Quark. Accept http.RoundTripper (not *http.Client) so tests can inject a transport.
Index ¶
- Variables
- func InterpolateRequest(req *domain.Request, colEnv, globalEnv map[string]string) (*domain.Request, error)
- func InterpolateRequestWithOverrides(req *domain.Request, positionals []string, ...) (*domain.Request, error)
- func ResolveEnvVars(ctx context.Context, r EnvResolver, collectionID string) (colEnv, globalEnv map[string]string, err error)
- func WithExecutionWriter(w ExecutionWriter) executionWriterOption
- func WithLogger(l *slog.Logger) loggerOption
- func WithMaxResponseSize(n int) maxRespSizeOption
- func WithPostResponseHooks(hooks []PostResponseHook) postHooksOption
- func WithPreRequestHooks(hooks []PreRequestHook) preHooksOption
- func WithTimeout(d time.Duration) timeoutOption
- func WithVariableResolver(r VariableResolver) variableResolverOption
- type EnvResolver
- type EnvironmentScope
- type ExecuteResult
- type ExecutionWriter
- type Executor
- type Option
- type PostResponseHook
- type PreRequestHook
- type VariableResolver
Constants ¶
This section is empty.
Variables ¶
var ( ErrTimeout = errors.New("request timed out") ErrRequestCancelled = errors.New("request cancelled") ErrInvalidURL = errors.New("invalid URL") )
Sentinel errors — use errors.Is to classify at the call site.
var ( // ErrEnvironmentResolution classifies failures that occur before interpolation. ErrEnvironmentResolution = errors.New("environment resolution") // ErrCollectionHierarchy classifies missing, inconsistent, or cyclic ancestry. ErrCollectionHierarchy = errors.New("invalid collection hierarchy") // ErrEnvironmentOwnership classifies an environment returned for the wrong scope. ErrEnvironmentOwnership = errors.New("invalid environment ownership") // ErrMissingDefaultEnvironment classifies a violated collection invariant. ErrMissingDefaultEnvironment = errors.New("missing default environment") )
var ErrUnresolvedVariable = errors.New("unresolved variable")
ErrUnresolvedVariable is returned when a {{VAR}} placeholder has no match in the collection or global environment.
Functions ¶
func InterpolateRequest ¶
func InterpolateRequest( req *domain.Request, colEnv, globalEnv map[string]string, ) (*domain.Request, error)
InterpolateRequest replaces {{VAR}} placeholders in req using the provided environment variables. Collection variables take precedence over global variables. Returns a new domain.Request with substitutions applied; the input is not modified. Returns ErrUnresolvedVariable if any placeholder cannot be resolved.
func InterpolateRequestWithOverrides ¶
func InterpolateRequestWithOverrides( req *domain.Request, positionals []string, named, colEnv, globalEnv map[string]string, ) (*domain.Request, error)
InterpolateRequestWithOverrides extends interpolation with CLI-provided overrides. Positional arguments are exposed as {{1}}, {{2}}, etc. Named overrides take precedence over collection and global envs. Fallback syntax {{1|merchant_id}} tries candidates from left to right and errors only if none resolve.
func ResolveEnvVars ¶
func ResolveEnvVars( ctx context.Context, r EnvResolver, collectionID string, ) (colEnv, globalEnv map[string]string, err error)
ResolveEnvVars resolves environment variables with each collection's own active environment. The merge order is Global, then, from root to child, each collection's default environment followed by its active environment. A missing active selection means that collection contributes only default.
func WithExecutionWriter ¶
func WithExecutionWriter(w ExecutionWriter) executionWriterOption
WithExecutionWriter enables persistence of immutable execution history.
func WithLogger ¶
WithLogger sets a custom slog.Logger.
func WithMaxResponseSize ¶
func WithMaxResponseSize(n int) maxRespSizeOption
WithMaxResponseSize sets the in-memory threshold (bytes). Responses larger than this are streamed to a temp file and ExecuteResult.TempPath is set.
func WithPostResponseHooks ¶
func WithPostResponseHooks( hooks []PostResponseHook, ) postHooksOption
WithPostResponseHooks registers hooks to run after each HTTP response is received.
func WithPreRequestHooks ¶
func WithPreRequestHooks(hooks []PreRequestHook) preHooksOption
WithPreRequestHooks registers hooks to run before each HTTP dispatch.
func WithTimeout ¶
WithTimeout sets the per-request timeout.
func WithVariableResolver ¶
func WithVariableResolver(r VariableResolver) variableResolverOption
WithVariableResolver sets a resolver that maps collection IDs to environment variables. The resolver is called during Execute to substitute {{VAR}} placeholders in URL, Body, and Headers before the HTTP request is built.
Types ¶
type EnvResolver ¶
type EnvResolver interface {
GetCollection(ctx context.Context, id string) (*domain.Collection, error)
GetEnvironment(ctx context.Context, id string) (*domain.Environment, error)
GetGlobalEnvironment(ctx context.Context) (*domain.Environment, error)
GetActiveEnvironment(ctx context.Context, collectionID string) (string, error)
ListCollectionEnvironments(
ctx context.Context,
collectionID string,
) ([]*domain.Environment, error)
}
EnvResolver is the minimum interface needed to resolve environment variables. *store.Store satisfies this through duck typing.
type EnvironmentScope ¶ added in v1.2.1
type EnvironmentScope struct {
Collection *domain.Collection
Environments []*domain.Environment
}
EnvironmentScope is one validated collection layer and its environments. LoadEnvironmentHierarchy returns scopes ordered from root to the requested child.
func LoadEnvironmentHierarchy ¶ added in v1.2.1
func LoadEnvironmentHierarchy( ctx context.Context, r EnvResolver, collectionID string, ) ([]EnvironmentScope, error)
LoadEnvironmentHierarchy loads and validates collection scopes from root to child.
type ExecuteResult ¶
type ExecuteResult struct {
StatusCode int
Status string // e.g. "200 OK"
// Headers is in canonical MIME title-case (http.CanonicalHeaderKey).
// Use http.Header(r.Headers).Get("content-type") for case-insensitive access.
// Do not use direct map key lookup.
Headers map[string][]string
Body []byte // nil if body was streamed to TempPath
TempPath string // non-empty if body > streaming threshold; call Cleanup() when done
Duration time.Duration
Size int64
}
ExecuteResult holds the outcome of a single HTTP dispatch. error is always its own return value — never part of this struct.
Lifecycle: if TempPath is non-empty, the caller owns the temp file. Call Cleanup() when finished rendering the response to remove it.
func (*ExecuteResult) Cleanup ¶
func (r *ExecuteResult) Cleanup() error
Cleanup removes the temp file if the response was streamed to disk. Safe to call even when TempPath is empty. Callers must call this when they are finished reading the response.
func (*ExecuteResult) IsStreamed ¶
func (r *ExecuteResult) IsStreamed() bool
IsStreamed reports whether the response body was written to a temp file.
type ExecutionWriter ¶
ExecutionWriter persists immutable execution history entries.
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor dispatches HTTP requests and returns structured results.
func New ¶
func New(transport http.RoundTripper, opts ...Option) *Executor
New constructs an Executor with the given transport and options. Pass http.DefaultTransport in production; inject httptest transports in tests.
func (*Executor) Execute ¶
Execute dispatches the request and returns a structured result. HTTP 4xx/5xx are not Go errors — they are valid responses. Check StatusCode. Returns nil, error only for network errors, timeouts, and context cancellation.
Hook dispatch order:
- Pre-request hooks fire in registration order. Any hook error aborts the request.
- Variable substitution (if VariableResolver is configured).
- HTTP dispatch.
- Post-response hooks fire in registration order. Hook errors are logged via slog.Warn; the next hook still fires regardless.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures an Executor. Use the With* functions in this package. This interface is sealed: only types in this package can implement it.
type PostResponseHook ¶
type PostResponseHook interface {
AfterResponse(ctx context.Context, req *domain.Request, res *ExecuteResult) error
}
PostResponseHook runs after a response is received (and after body read). Errors are logged and do not fail Execute.
type PreRequestHook ¶
type PreRequestHook interface {
BeforeRequest(ctx context.Context, req *domain.Request) (*domain.Request, error)
}
PreRequestHook runs before an HTTP request is dispatched. Hooks can mutate or replace the request; returning an error aborts Execute.
type VariableResolver ¶
VariableResolver resolves environment variables for a collection. Returns (collectionEnv, globalEnv) or a resolution error. The resolver is called synchronously during Execute, before building the HTTP request.