response

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package response provides Response-step middleware for CORS, caching, field transforms, custom envelopes, and observability.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddHeader

func AddHeader(key, value string) maniflex.MiddlewareFunc

AddHeader unconditionally adds an HTTP response header.

server.Pipeline.Response.Register(
    response.AddHeader("X-Powered-By", "maniflex"),
    maniflex.AtPosition(maniflex.After),
)

func CORSHeaders

func CORSHeaders(allowedOrigins ...string) maniflex.MiddlewareFunc

CORSHeaders sets CORS response headers on every response, and returns 200 for OPTIONS preflight requests. Register this on the Response step with AtPosition(After).

At least one origin is required — pass explicit origins (recommended) or "*" to allow any origin. Calling it with no origins panics, so a permissive wildcard is never applied by accident (SEC-6). For credentials or custom allowed headers/methods/max-age, use CORSHeadersWithConfig.

server.Pipeline.Response.Register(
    response.CORSHeaders("https://myapp.com"),
    maniflex.AtPosition(maniflex.After),
)

func CORSHeadersWithConfig added in v0.1.4

func CORSHeadersWithConfig(cfg CORSConfig) maniflex.MiddlewareFunc

CORSHeadersWithConfig is CORSHeaders with full control over allowed headers, methods, preflight max-age, and credentials. cfg.AllowOrigins is required (empty panics), and a "*" origin combined with AllowCredentials panics because browsers reject that combination.

server.Pipeline.Response.Register(
    response.CORSHeadersWithConfig(response.CORSConfig{
        AllowOrigins:     []string{"https://myapp.com"},
        AllowCredentials: true,
    }),
    maniflex.AtPosition(maniflex.After),
)

func Cache

func Cache(maxAgeSeconds int) maniflex.MiddlewareFunc

Cache sets Cache-Control and ETag headers on read responses. It is a no-op on write operations (create, update, delete).

server.Pipeline.Response.Register(
    response.Cache(300), // 5 minutes
    maniflex.ForOperation(maniflex.OpRead, maniflex.OpList),
    maniflex.AtPosition(maniflex.After),
)

func Envelope

Envelope replaces the default {"data": ..., "meta": ...} response structure with a custom one. Register it with AtPosition(After) on the Response step.

server.Pipeline.Response.Register(
    response.Envelope(func(ctx *maniflex.ServerContext, data any, meta *maniflex.ResponseMeta) any {
        out := map[string]any{"result": data, "ok": true}
        if meta != nil {
            out["pagination"] = meta
        }
        return out
    }),
    maniflex.AtPosition(maniflex.After),
)

func Logging

func Logging(logger *slog.Logger) maniflex.MiddlewareFunc

Logging emits a structured log line after every request using slog. Register it with AtPosition(After) on the Response step.

server.Pipeline.Response.Register(
    response.Logging(slog.Default()),
    maniflex.AtPosition(maniflex.After),
)

func Metrics

func Metrics(collector MetricsCollector) maniflex.MiddlewareFunc

Metrics records request counters and latency histograms. Register it with AtPosition(After) on the Response step.

server.Pipeline.Response.Register(
    response.Metrics(myCollector),
    maniflex.AtPosition(maniflex.After),
)

func RedactField

func RedactField(field string, shouldRedact func(ctx *maniflex.ServerContext) bool) maniflex.MiddlewareFunc

RedactField removes a field from the response dynamically, based on a condition. Unlike the static mfx:"hidden" tag this can check ctx.Auth.

// Hide phone unless the caller has the "support" role
server.Pipeline.Response.Register(
    response.RedactField("phone", func(ctx *maniflex.ServerContext) bool {
        return !ctx.HasRole("support")
    }),
    maniflex.ForModel("User"),
    maniflex.AtPosition(maniflex.After),
)

func TransformField

func TransformField(field string, fn TransformFunc) maniflex.MiddlewareFunc

TransformField applies fn to the named field in every item of the response data. Works on both single-record and list responses.

// Prefix avatar URLs with a CDN base
server.Pipeline.Response.Register(
    response.TransformField("avatar_url", func(v any) any {
        if s, ok := v.(string); ok && s != "" {
            return "https://cdn.example.com/" + s
        }
        return v
    }),
    maniflex.ForModel("User"),
    maniflex.AtPosition(maniflex.After),
)

Types

type CORSConfig

type CORSConfig struct {
	// AllowOrigins is the list of allowed origins. It is REQUIRED: construction
	// panics if it is empty, so a permissive wildcard is never applied by
	// accident. Use ["*"] to explicitly allow any origin (public APIs only — it
	// cannot be combined with AllowCredentials).
	AllowOrigins []string
	// AllowHeaders are the headers a browser may send. Default: common safe set.
	AllowHeaders []string
	// AllowMethods are the HTTP methods to allow. Default: GET, POST, PATCH, DELETE, OPTIONS.
	AllowMethods []string
	// MaxAge is the preflight cache duration in seconds. Default: 86400 (24h).
	MaxAge int
	// AllowCredentials sets Access-Control-Allow-Credentials. Default: false.
	// It cannot be combined with a "*" wildcard origin (the Fetch spec forbids
	// that combination); doing so panics at construction.
	AllowCredentials bool
}

CORSConfig configures CORS header behaviour.

type EnvelopeFunc

type EnvelopeFunc func(ctx *maniflex.ServerContext, data any, meta *maniflex.ResponseMeta) any

EnvelopeFunc wraps the outgoing response data in a custom structure. Return a new map to replace the default {"data": ...} envelope.

type MetricsCollector

type MetricsCollector interface {
	// IncCounter increments a counter with the given labels.
	IncCounter(name string, labels map[string]string)
	// ObserveHistogram records a duration observation.
	ObserveHistogram(name string, value float64, labels map[string]string)
}

MetricsCollector is satisfied by any metrics library. Implement it to bridge to Prometheus, Datadog, StatsD, etc.

type TransformFunc

type TransformFunc func(value any) any

TransformFunc maps one field value to another in the response.

Jump to

Keyboard shortcuts

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