apptheory

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const RateLimitDecisionKey = "rate_limit_decision"

RateLimitDecisionKey is the Context key used by RateLimitMiddleware to store the last LimitDecision.

Variables

This section is empty.

Functions

func CacheControlISR

func CacheControlISR(revalidateSeconds, staleWhileRevalidateSeconds int) string

CacheControlISR returns a Cache-Control value suitable for ISR (edge-cached with stale-while-revalidate).

func CacheControlSSG

func CacheControlSSG() string

CacheControlSSG returns a Cache-Control value suitable for edge-cached SSG HTML (no browser caching).

func CacheControlSSR

func CacheControlSSR() string

CacheControlSSR returns a conservative Cache-Control value for dynamic SSR.

func CaptureBodyStream

func CaptureBodyStream(ctx context.Context, stream BodyStream) ([][]byte, []byte, error)

CaptureBodyStream reads the provided stream until completion, context cancellation, or error.

It returns the captured chunks, concatenated body bytes, and an error if one occurred.

func ClientIP

func ClientIP(headers map[string][]string) string

ClientIP extracts a stable client IP address from CloudFront and generic forwarded headers.

func ETag

func ETag(body []byte) string

ETag returns a deterministic, strong ETag for the provided bytes.

The returned value includes quotes (e.g. `"abc..."`).

func IsLambda

func IsLambda() bool

func MatchesIfNoneMatch

func MatchesIfNoneMatch(headers map[string][]string, etag string) bool

MatchesIfNoneMatch reports whether the request headers contain an If-None-Match value that matches the given etag.

func OriginURL

func OriginURL(headers map[string][]string) string

OriginURL reconstructs the canonical origin URL (scheme + host) from forwarded headers.

func SafeJSONForHTML

func SafeJSONForHTML(value any) (string, error)

SafeJSONForHTML serializes a value as JSON with escaping suitable for embedding into HTML.

It escapes `<`, `>`, `&`, U+2028, and U+2029 to prevent script-breaking sequences and cross-language drift.

func StepFunctionsTaskToken

func StepFunctionsTaskToken(event any) string

StepFunctionsTaskToken extracts an AWS Step Functions callback task token from common payload shapes.

It checks (in order): "taskToken", "TaskToken", and "task_token". If no token is found, it returns "".

func Vary

func Vary(existing []string, add ...string) []string

Vary merges Vary header values with deterministic ordering.

Values are split on commas, trimmed, lowercased, de-duplicated, and sorted.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App is the root container for an AppTheory application.

AppTheory's runtime behavior is defined by a fixture-backed, versioned contract: `docs/development/planning/apptheory/supporting/apptheory-runtime-contract-v0.md`.

func New

func New(opts ...Option) *App

New creates a new AppTheory application container.

func (*App) Delete

func (a *App) Delete(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) DeleteStrict

func (a *App) DeleteStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) DynamoDB

func (a *App) DynamoDB(tableName string, handler DynamoDBStreamHandler) *App

DynamoDB registers a DynamoDB Streams handler by table name.

func (*App) EventBridge

func (a *App) EventBridge(selector EventBridgeSelector, handler EventBridgeHandler) *App

EventBridge registers an EventBridge handler.

Matching rules: - If selector.RuleName is set, it matches when any event resource ARN refers to that rule name. - Otherwise, it matches on selector.Source + selector.DetailType (when provided).

func (*App) Get

func (a *App) Get(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) GetStrict

func (a *App) GetStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) Handle

func (a *App) Handle(method, pattern string, handler Handler, opts ...RouteOption) *App

func (*App) HandleLambda

func (a *App) HandleLambda(ctx context.Context, event json.RawMessage) (any, error)

HandleLambda routes an untyped Lambda event to the correct AppTheory entrypoint.

Supported triggers: - API Gateway v2 (HTTP API) - API Gateway REST API v1 (Proxy) - Application Load Balancer (Target Group) - Lambda Function URL - SQS - Kinesis - SNS - EventBridge - DynamoDB Streams - API Gateway v2 (WebSocket API)

func (*App) HandleStrict

func (a *App) HandleStrict(method, pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) IsLambda

func (a *App) IsLambda() bool

func (*App) Kinesis

func (a *App) Kinesis(streamName string, handler KinesisHandler) *App

Kinesis registers a handler for a Kinesis stream by stream name.

func (*App) Options

func (a *App) Options(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) OptionsStrict

func (a *App) OptionsStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) Patch

func (a *App) Patch(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) PatchStrict

func (a *App) PatchStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) Post

func (a *App) Post(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) PostStrict

func (a *App) PostStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) Put

func (a *App) Put(pattern string, handler Handler, opts ...RouteOption) *App

func (*App) PutStrict

func (a *App) PutStrict(pattern string, handler Handler, opts ...RouteOption) (*App, error)

func (*App) SNS

func (a *App) SNS(topicName string, handler SNSHandler) *App

SNS registers a handler for an SNS topic by topic name.

func (*App) SQS

func (a *App) SQS(queueName string, handler SQSHandler) *App

SQS registers a handler for an SQS queue by queue name.

func (*App) Serve

func (a *App) Serve(ctx context.Context, req Request) (resp Response)

func (*App) ServeAPIGatewayProxy

func (a *App) ServeAPIGatewayProxy(ctx context.Context, event events.APIGatewayProxyRequest) events.APIGatewayProxyResponse

func (*App) ServeDynamoDBStream

func (a *App) ServeDynamoDBStream(ctx context.Context, event events.DynamoDBEvent) events.DynamoDBEventResponse

ServeDynamoDBStream routes a DynamoDB Streams event to the registered table handler and returns a partial batch failure response.

If the table is unrecognized, it fails closed by returning all records as failures.

func (*App) ServeEventBridge

func (a *App) ServeEventBridge(ctx context.Context, event events.EventBridgeEvent) (any, error)

ServeEventBridge routes an EventBridge event to the first matching handler.

If no handler matches, it returns (nil, nil).

func (*App) ServeKinesis

func (a *App) ServeKinesis(ctx context.Context, event events.KinesisEvent) events.KinesisEventResponse

ServeKinesis routes a Kinesis event to the registered stream handler and returns a partial batch failure response.

If the stream is unrecognized, it fails closed by returning all records as failures.

func (*App) ServeSNS

func (a *App) ServeSNS(ctx context.Context, event events.SNSEvent) ([]any, error)

ServeSNS routes an SNS event to the registered topic handler.

If the topic is unrecognized, it fails closed by returning an error.

The returned output value is ignored by AWS for SNS triggers, but is useful for tests and local invocation tooling.

func (*App) ServeSQS

func (a *App) ServeSQS(ctx context.Context, event events.SQSEvent) events.SQSEventResponse

ServeSQS routes an SQS event to the registered queue handler and returns a partial batch failure response.

If the queue is unrecognized, it fails closed by returning all messages as failures.

func (*App) ServeWebSocket

func (*App) Use

func (a *App) Use(mw Middleware) *App

Use registers a global middleware.

func (*App) UseEvents

func (a *App) UseEvents(mw EventMiddleware) *App

UseEvents registers a global event middleware.

Event middleware is applied in registration order:

app.UseEvents(m1).UseEvents(m2)

yields the execution order:

m1 -> m2 -> event handler

func (*App) WebSocket

func (a *App) WebSocket(routeKey string, handler WebSocketHandler) *App

type AppError

type AppError struct {
	Code    string
	Message string
}

AppError is a portable, client-safe error with a stable error code.

func (*AppError) Error

func (e *AppError) Error() string

type AppTheoryError added in v0.7.0

type AppTheoryError struct {
	Code       string
	Message    string
	StatusCode int
	Details    map[string]any
	RequestID  string
	TraceID    string
	Timestamp  time.Time
	StackTrace string
	Cause      error
}

AppTheoryError is a portable, client-safe error with optional metadata for observability and debugging.

func AppTheoryErrorFromAppError added in v0.7.0

func AppTheoryErrorFromAppError(err *AppError) *AppTheoryError

func AsAppTheoryError added in v0.7.0

func AsAppTheoryError(err error) (*AppTheoryError, bool)

func NewAppTheoryError added in v0.7.0

func NewAppTheoryError(code, message string) *AppTheoryError

func (*AppTheoryError) Error added in v0.7.0

func (e *AppTheoryError) Error() string

func (*AppTheoryError) Unwrap added in v0.7.0

func (e *AppTheoryError) Unwrap() error

func (*AppTheoryError) WithCause added in v0.7.0

func (e *AppTheoryError) WithCause(err error) *AppTheoryError

func (*AppTheoryError) WithDetails added in v0.7.0

func (e *AppTheoryError) WithDetails(details map[string]any) *AppTheoryError

func (*AppTheoryError) WithRequestID added in v0.7.0

func (e *AppTheoryError) WithRequestID(requestID string) *AppTheoryError

func (*AppTheoryError) WithStackTrace added in v0.7.0

func (e *AppTheoryError) WithStackTrace(stackTrace string) *AppTheoryError

func (*AppTheoryError) WithStatusCode added in v0.7.0

func (e *AppTheoryError) WithStatusCode(statusCode int) *AppTheoryError

func (*AppTheoryError) WithTimestamp added in v0.7.0

func (e *AppTheoryError) WithTimestamp(timestamp time.Time) *AppTheoryError

func (*AppTheoryError) WithTraceID added in v0.7.0

func (e *AppTheoryError) WithTraceID(traceID string) *AppTheoryError

type AuthHook

type AuthHook func(*Context) (identity string, err error)

type BodyStream

type BodyStream <-chan StreamChunk

BodyStream is a portable stream-of-bytes response body.

It is represented as a channel of chunks so callers can deterministically capture chunk boundaries in tests.

func StreamBytes

func StreamBytes(chunks ...[]byte) BodyStream

StreamBytes builds a BodyStream from an ordered list of byte chunks.

func StreamError

func StreamError(err error) BodyStream

StreamError emits a terminal stream error.

type CORSConfig

type CORSConfig struct {
	AllowedOrigins   []string
	AllowCredentials bool
	AllowHeaders     []string
}

type Clock

type Clock interface {
	Now() time.Time
}

Clock provides deterministic time for handlers and middleware.

type Context

type Context struct {
	Request Request
	Params  map[string]string

	RequestID       string
	TenantID        string
	AuthIdentity    string
	RemainingMS     int
	MiddlewareTrace []string
	// contains filtered or unexported fields
}

Context is the per-request context passed to handlers.

func (*Context) AsWebSocket

func (c *Context) AsWebSocket() *WebSocketContext

func (*Context) Context

func (c *Context) Context() context.Context

func (*Context) Get

func (c *Context) Get(key string) any

func (*Context) JSONValue

func (c *Context) JSONValue() (any, error)

func (*Context) NewID

func (c *Context) NewID() string

func (*Context) Now

func (c *Context) Now() time.Time

func (*Context) Param

func (c *Context) Param(name string) string

func (*Context) Set

func (c *Context) Set(key string, value any)

type DynamoDBStreamHandler

type DynamoDBStreamHandler func(*EventContext, events.DynamoDBEventRecord) error

type EventBridgeHandler

type EventBridgeHandler func(*EventContext, events.EventBridgeEvent) (any, error)

type EventBridgeSelector

type EventBridgeSelector struct {
	RuleName   string
	Source     string
	DetailType string
}

func EventBridgePattern

func EventBridgePattern(source, detailType string) EventBridgeSelector

func EventBridgeRule

func EventBridgeRule(ruleName string) EventBridgeSelector

type EventContext

type EventContext struct {
	RequestID   string
	RemainingMS int
	// contains filtered or unexported fields
}

EventContext is the shared context for non-HTTP Lambda triggers (SQS, EventBridge, DynamoDB Streams).

func (*EventContext) Context

func (c *EventContext) Context() context.Context

func (*EventContext) Get

func (c *EventContext) Get(key string) any

func (*EventContext) NewID

func (c *EventContext) NewID() string

func (*EventContext) Now

func (c *EventContext) Now() time.Time

func (*EventContext) Set

func (c *EventContext) Set(key string, value any)

type EventHandler

type EventHandler func(*EventContext, any) (any, error)

EventHandler is a generic handler function for non-HTTP Lambda triggers.

The `event` value is trigger-specific (for example: `events.SQSMessage`, `events.DynamoDBEventRecord`, `events.EventBridgeEvent`).

type EventMiddleware

type EventMiddleware func(EventHandler) EventHandler

EventMiddleware wraps an EventHandler.

Event middleware is opt-in: it only runs when registered via `app.UseEvents(...)`.

type Handler

type Handler func(*Context) (*Response, error)

Handler is the request handler signature for AppTheory apps.

func JSONHandler added in v0.8.0

func JSONHandler[Req, Resp any](handler func(*Context, Req) (Resp, error)) Handler

JSONHandler adapts a typed JSON handler into an AppTheory Handler.

It parses the request body as JSON into Req, invokes the typed handler, and returns a 200 JSON response with the handler's response value.

On empty or invalid JSON bodies, it returns a 400 AppTheoryError with Lift-compatible error codes/messages.

func JSONHandlerContext added in v0.8.0

func JSONHandlerContext[Req, Resp any](handler func(context.Context, Req) (Resp, error)) Handler

JSONHandlerContext adapts a typed JSON handler that uses context.Context.

type IDGenerator

type IDGenerator interface {
	NewID() string
}

IDGenerator provides randomness for IDs/correlation IDs.

type IdGenerator

type IdGenerator = IDGenerator

IdGenerator is an alias for IDGenerator (cross-language naming parity).

type KinesisHandler

type KinesisHandler func(*EventContext, events.KinesisEventRecord) error

type Limits

type Limits struct {
	MaxRequestBytes  int
	MaxResponseBytes int
}

type LogRecord

type LogRecord struct {
	Level     string
	Event     string
	RequestID string
	TenantID  string
	Method    string
	Path      string
	Status    int
	ErrorCode string
}

type MetricRecord

type MetricRecord struct {
	Name  string
	Value int
	Tags  map[string]string
}

type Middleware

type Middleware func(Handler) Handler

Middleware wraps an AppTheory handler.

Middleware is applied in registration order:

app.Use(m1).Use(m2)

yields the execution order:

m1 -> m2 -> handler

func RateLimitMiddleware

func RateLimitMiddleware(config RateLimitConfig) Middleware

func TimeoutMiddleware

func TimeoutMiddleware(config TimeoutConfig) Middleware

type ObservabilityHooks

type ObservabilityHooks struct {
	Log    func(LogRecord)
	Metric func(MetricRecord)
	Span   func(SpanRecord)
}

type Option

type Option func(*App)

func WithAuthHook

func WithAuthHook(hook AuthHook) Option

func WithCORS

func WithCORS(config CORSConfig) Option

func WithClock

func WithClock(clock Clock) Option

func WithIDGenerator

func WithIDGenerator(ids IDGenerator) Option

func WithLimits

func WithLimits(limits Limits) Option

func WithObservability

func WithObservability(hooks ObservabilityHooks) Option

func WithPolicyHook

func WithPolicyHook(hook PolicyHook) Option

func WithTier

func WithTier(tier Tier) Option

func WithWebSocketClientFactory

func WithWebSocketClientFactory(factory WebSocketClientFactory) Option

func WithWebSocketSupport

func WithWebSocketSupport() Option

type PolicyDecision

type PolicyDecision struct {
	Code    string
	Message string
	Headers map[string][]string
}

type PolicyHook

type PolicyHook func(*Context) (*PolicyDecision, error)

type RandomIDGenerator

type RandomIDGenerator struct{}

RandomIDGenerator generates IDs using cryptographic randomness.

func (RandomIDGenerator) NewID

func (RandomIDGenerator) NewID() string

type RandomIdGenerator

type RandomIdGenerator = RandomIDGenerator

RandomIdGenerator is an alias for RandomIDGenerator (cross-language naming parity).

type RateLimitConfig

type RateLimitConfig struct {
	// Limiter is required. If nil, RateLimitMiddleware is a no-op.
	Limiter limited.RateLimiter

	// FailClosed controls behavior when the limiter returns an error.
	// If false (default), requests proceed on limiter errors.
	FailClosed bool

	ExtractIdentifier func(ctx *Context) string
	ExtractResource   func(ctx *Context) string
	ExtractOperation  func(ctx *Context) string

	OnError     func(ctx *Context, err error)
	OnSuccess   func(ctx *Context, decision *limited.LimitDecision)
	OnRateLimit func(ctx *Context, decision *limited.LimitDecision)
}

type RealClock

type RealClock struct{}

RealClock uses time.Now.

func (RealClock) Now

func (RealClock) Now() time.Time

type Request

type Request struct {
	Method string
	Path   string
	Query  map[string][]string
	// Headers are canonicalized to lowercase keys during request normalization.
	// Treat header names as case-insensitive and prefer lowercase when accessing values.
	Headers  map[string][]string
	Cookies  map[string]string
	Body     []byte
	IsBase64 bool
}

Request is the canonical HTTP request model used by the AppTheory runtime.

type Response

type Response struct {
	Status int
	// Headers are canonicalized to lowercase keys during response normalization.
	// Treat header names as case-insensitive and prefer lowercase when accessing values.
	Headers map[string][]string
	// Cookies contains raw Set-Cookie header values. If you also provide a "set-cookie"
	// header in Headers, normalization merges it into Cookies.
	Cookies    []string
	Body       []byte
	BodyReader io.Reader
	BodyStream BodyStream
	IsBase64   bool
}

Response is the canonical HTTP response model returned by AppTheory handlers.

func Binary

func Binary(status int, body []byte, contentType string) *Response

Binary builds a base64-encoded response for binary body content.

func HTML

func HTML(status int, body any) *Response

HTML builds a text/html response (utf-8).

body supports string and []byte inputs.

func HTMLStream

func HTMLStream(status int, stream BodyStream) *Response

HTMLStream builds a streaming text/html response (utf-8).

func JSON

func JSON(status int, value any) (*Response, error)

JSON builds an application/json response (utf-8).

func MustJSON

func MustJSON(status int, value any) *Response

MustJSON builds an application/json response (utf-8) and panics on marshal failure.

func MustSSEResponse

func MustSSEResponse(status int, events ...SSEEvent) *Response

MustSSEResponse builds an SSE response and panics on framing/serialization errors.

func SSEResponse

func SSEResponse(status int, events ...SSEEvent) (*Response, error)

SSEResponse builds a canonical AppTheory Response with properly framed SSE output.

func SSEStreamResponse

func SSEStreamResponse(ctx context.Context, status int, events <-chan SSEEvent) (*Response, error)

SSEStreamResponse builds a canonical AppTheory Response with event-by-event SSE output.

The returned response uses response streaming when invoked through the API Gateway REST API v1 adapter (`ServeAPIGatewayProxy` via `HandleLambda`).

func Text

func Text(status int, body string) *Response

Text builds a text/plain response (utf-8).

type RouteOption

type RouteOption func(*routeOptions)

func RequireAuth

func RequireAuth() RouteOption

type SNSHandler

type SNSHandler func(*EventContext, events.SNSEventRecord) (any, error)

type SQSHandler

type SQSHandler func(*EventContext, events.SQSMessage) error

type SSEEvent

type SSEEvent struct {
	ID    string
	Event string
	Data  any
}

SSEEvent is a Server-Sent Events (SSE) message.

Framing rules: - Optional: "id: <id>\n" - Optional: "event: <event>\n" - Data: one "data: <line>\n" per line (at least one line) - Terminator: "\n"

type SpanRecord

type SpanRecord struct {
	Name       string
	Attributes map[string]string
}

type StreamChunk

type StreamChunk struct {
	Bytes []byte
	Err   error
}

StreamChunk is a single streaming response body chunk.

If Err is non-nil, the stream MUST terminate and callers MUST treat it as a stream error.

type Tier

type Tier string
const (
	TierP0 Tier = "p0"
	TierP1 Tier = "p1"
	TierP2 Tier = "p2"
)

type TimeoutConfig

type TimeoutConfig struct {
	DefaultTimeout    time.Duration
	OperationTimeouts map[string]time.Duration
	TenantTimeouts    map[string]time.Duration
	TimeoutMessage    string
}

type WebSocketClientFactory

type WebSocketClientFactory func(context.Context, string) (streamer.Client, error)

type WebSocketContext

type WebSocketContext struct {
	RequestID   string
	RemainingMS int

	ConnectionID       string
	RouteKey           string
	DomainName         string
	Stage              string
	EventType          string
	ManagementEndpoint string

	Body []byte
	// contains filtered or unexported fields
}

func (*WebSocketContext) Context

func (c *WebSocketContext) Context() context.Context

func (*WebSocketContext) NewID

func (c *WebSocketContext) NewID() string

func (*WebSocketContext) Now

func (c *WebSocketContext) Now() time.Time

func (*WebSocketContext) SendJSONMessage

func (c *WebSocketContext) SendJSONMessage(value any) error

func (*WebSocketContext) SendMessage

func (c *WebSocketContext) SendMessage(data []byte) error

type WebSocketHandler

type WebSocketHandler func(*Context) (*Response, error)

Directories

Path Synopsis
Package oauth provides small, composable OAuth 2.0/2.1 primitives used by AppTheory components (e.g.
Package oauth provides small, composable OAuth 2.0/2.1 primitives used by AppTheory components (e.g.

Jump to

Keyboard shortcuts

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