exec

package
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package exec implements HTTP request execution for Quark. Accept http.RoundTripper (not *http.Client) so tests can inject a transport.

Index

Constants

This section is empty.

Variables

View Source
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.

View Source
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")
)
View Source
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

func WithLogger(l *slog.Logger) loggerOption

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

func WithTimeout(d time.Duration) timeoutOption

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

type ExecutionWriter interface {
	SaveExecution(ctx context.Context, ex *domain.Execution) error
}

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

func (e *Executor) Execute(ctx context.Context, req *domain.Request) (*ExecuteResult, error)

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:

  1. Pre-request hooks fire in registration order. Any hook error aborts the request.
  2. Variable substitution (if VariableResolver is configured).
  3. HTTP dispatch.
  4. 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

type VariableResolver func(collectionID string) (colEnv, globalEnv map[string]string, err error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL