aarv

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 30 Imported by: 0

README

Aarv

The peaceful sound of minimal Go.

Go Reference Tests License Go Report Card


Aarv is a lightweight, zero-dependency Go web framework built on top of net/http.

Inspired by .NET Minimal API (type-safe binding, fluent registration) and Fastify (plugins, lifecycle hooks, encapsulation).

Features

  • Zero external dependencies in core — pure Go stdlib
  • Go 1.22+ ServeMux routing with method patterns, path params, and wildcards
  • Type-safe request binding via Go generics (Bind[Req, Res])
  • Multi-source binding — path params, query, headers, cookies, body, form — all via struct tags
  • Built-in validation engine — struct tag rules, pre-computed at registration, zero-alloc hot path
  • Fastify-style lifecycle hooks — OnRequest, PreHandler, OnResponse, OnSend, OnError, and more
  • Scoped plugin system — encapsulated plugins with decorators, nested registration
  • Middleware compatible — standard func(http.Handler) http.Handler works out of the box
  • Pooled Contextsync.Pool recycled context for minimal GC pressure
  • Pluggable JSON codec — swap encoding/json for segmentio, sonic, or json/v2
  • Graceful shutdown with signal handling and drain timeout
  • TLS / HTTP/2 / mTLS — production-ready with sensible defaults

Quick Start

package main

import "github.com/nilshah80/aarv"

func main() {
    app := aarv.New()

    app.Get("/hello", func(c *aarv.Context) error {
        return c.JSON(200, map[string]string{"message": "hello, world"})
    })

    app.Listen(":8080")
}

Examples

Concrete examples live under examples/:

  • examples/hello — minimal routes, Bind, route groups
  • examples/rest-crud — CRUD-style app structure
  • examples/hooks — full lifecycle hooks including PreRouting, PreParsing, PreValidation, PreHandler, OnError
  • examples/route-groups — nested route groups with scoped middleware
  • examples/binding — multi-source binding across path, query, header, and JSON body
  • examples/error-handling — custom error handler plus OnError
  • examples/custom-middleware — stdlib-only, native-only, and dual-registered middleware
  • examples/middleware-bridge — stdlib middleware using r.WithContext(...) with Aarv compatibility
  • examples/json-logger — structured logging
  • examples/encrypt — AES-GCM request/response encryption
  • examples/custom-plugin — decorators, dependencies, plugin-scoped routes, dual middleware registration
  • examples/auth — JWT, API key, and session auth
  • examples/database — repository-style app with typed handlers
  • examples/fileserver and examples/streaming — file and stream responses

Type-Safe Handlers

type CreateUserReq struct {
    Name  string `json:"name"  validate:"required,min=2"`
    Email string `json:"email" validate:"required,email"`
}

type CreateUserRes struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

app.Post("/users", aarv.Bind(func(c *aarv.Context, req CreateUserReq) (CreateUserRes, error) {
    // req is already parsed, validated, and typed
    return CreateUserRes{ID: "123", Name: req.Name, Email: req.Email}, nil
}))

Multi-Source Binding

type GetOrderReq struct {
    UserID  string `param:"userId"`
    OrderID int    `param:"orderId"`
    Fields  string `query:"fields"  default:"*"`
    Token   string `header:"X-Api-Key"`
}

app.Get("/users/{userId}/orders/{orderId}", aarv.BindReq(func(c *aarv.Context, req GetOrderReq) error {
    // req.UserID from path, req.Fields from query, req.Token from header
    return c.JSON(200, getOrder(req))
}))

Route Groups & Middleware

app.Use(aarv.Recovery(), aarv.Logger())

app.Group("/api/v1", func(g *aarv.RouteGroup) {
    g.Use(authMiddleware)

    g.Get("/users", listUsers)
    g.Post("/users", aarv.Bind(createUser))

    g.Group("/admin", func(ag *aarv.RouteGroup) {
        ag.Use(adminOnly)
        ag.Delete("/users/{id}", deleteUser)
    })
})

Middleware Modes

Aarv supports two middleware styles:

  • stdlib-compatible: func(http.Handler) http.Handler
  • Aarv-native: func(next aarv.HandlerFunc) aarv.HandlerFunc

Stdlib middleware is the compatibility path. It works with ordinary Go middleware and preserves Aarv context across r.WithContext(...) clones by default.

Aarv-native middleware is the faster path. Use aarv.WrapMiddleware(...) for custom middleware that needs *aarv.Context directly:

app.Use(aarv.WrapMiddleware(func(next aarv.HandlerFunc) aarv.HandlerFunc {
    return func(c *aarv.Context) error {
        c.SetHeader("X-Trace", "on")
        return next(c)
    }
}))

For middleware-heavy services that never rely on Aarv context recovery from cloned requests, WithRequestContextBridge(false) remains an opt-in fast mode.

Lifecycle Hooks

app.AddHook(aarv.OnRequest, func(c *aarv.Context) error {
    c.Set("startTime", time.Now())
    return nil
})

app.AddHook(aarv.OnResponse, func(c *aarv.Context) error {
    start, _ := aarv.GetTyped[time.Time](c, "startTime")
    c.Logger().Info("request completed", "latency", time.Since(start))
    return nil
})

Plugins

app.Register(aarv.PluginFunc(func(p *aarv.PluginContext) error {
    p.Decorate("db", connectDB())
    p.Get("/health", healthCheck)
    return nil
}))

Pluggable JSON Codec

import "github.com/nilshah80/aarv/codec/segmentio"

app := aarv.New(aarv.WithCodec(segmentio.New()))

Performance Notes

The core framework stays zero-dependency and production-oriented. The requestid plugin is opt-in, but Aarv preserves framework context across raw r.WithContext(...) middleware clones by default so standard Go middleware keeps working.

WithRequestContextBridge(false) is an opt-in mode for middleware-heavy services that never rely on aarv.FromRequest(...) after cloning requests with r.WithContext(...).

Use it when:

  • your middleware stack does not need Aarv context recovery from cloned requests
  • you want the leanest compatibility tradeoff for fully controlled middleware stacks

Do not use it when:

  • standard middleware calls r.WithContext(...) and downstream code expects aarv.FromRequest(...) to still work on the cloned request
  • you need the default compatibility behavior across mixed stdlib middleware

Example:

app := aarv.New(
    aarv.WithBanner(false),
    aarv.WithRequestContextBridge(false),
)

Architecture

Request → Global Middleware → ServeMux Route Match → Group Middleware → Hooks → Bind → Validate → Handler → Response
            ↕ sync.Pool Context    ↕ Pluggable Codec    ↕ Buffered Writer    ↕ Error Handler

Philosophy

  • Minimal — thin layer over net/http, not a replacement
  • Zero-dep core — everything in the core uses only the Go standard library
  • Fast — pooled contexts, pre-computed binders/validators, pre-built middleware chains
  • Familiar — standard middleware signature, standard handler patterns, nothing magical
  • Pluggable — swap JSON codec, validator, error handler, logger — all via interfaces

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrResponseAlreadyWritten is returned when attempting to write to a response
	// that has already been written to.
	ErrResponseAlreadyWritten = errors.New("aarv: response already written")
)

Sentinel errors for common conditions.

Functions

func GetTyped

func GetTyped[T any](c *Context, key string) (T, bool)

GetTyped retrieves a typed value from the context store.

func RegisterRule

func RegisterRule(name string, fn CustomRuleFunc)

RegisterRule registers a custom validation rule. The rule can then be used in validate tags like: validate:"myrule=param"

func RegisterStructValidation

func RegisterStructValidation(t reflect.Type, fn StructLevelFunc)

RegisterStructValidation registers a struct-level validation function for a specific type.

func SetValidationMessageTemplate added in v0.4.0

func SetValidationMessageTemplate(tag string, fn ValidationMessageFunc)

SetValidationMessageTemplate overrides the default message for a validation rule. Passing a nil function removes the custom template for the rule.

Types

type App

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

App is the central framework instance.

func New

func New(opts ...Option) *App

New creates a new App with the given options.

func (*App) AcquireContext

func (a *App) AcquireContext(w http.ResponseWriter, r *http.Request) *Context

AcquireContext gets a Context from the pool. Must be followed by ReleaseContext.

func (*App) AddHook

func (a *App) AddHook(phase HookPhase, fn HookFunc) *App

AddHook registers a lifecycle hook.

func (*App) AddHookWithPriority

func (a *App) AddHookWithPriority(phase HookPhase, priority int, fn HookFunc) *App

AddHookWithPriority registers a hook with priority (lower = runs first).

func (*App) Any

func (a *App) Any(pattern string, handler any, opts ...RouteOption) *App

Any registers the handler for the common HTTP methods on the same pattern.

func (*App) Delete

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

Delete registers a DELETE route for the given pattern.

func (*App) Get

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

Get registers a GET route for the given pattern.

func (*App) Group

func (a *App) Group(prefix string, fn func(g *RouteGroup)) *App

Group creates a route group with a prefix.

func (*App) Head

func (a *App) Head(pattern string, handler any, opts ...RouteOption) *App

Head registers a HEAD route for the given pattern.

func (*App) Listen

func (a *App) Listen(addr string) error

Listen starts the HTTP server and blocks until shutdown.

func (*App) ListenMutualTLS

func (a *App) ListenMutualTLS(addr, certFile, keyFile, clientCAFile string) error

ListenMutualTLS starts the server with mutual TLS authentication.

func (*App) ListenTLS

func (a *App) ListenTLS(addr, certFile, keyFile string) error

ListenTLS starts the HTTPS server with TLS.

func (*App) Mount

func (a *App) Mount(prefix string, handler http.Handler) *App

Mount mounts a standard library http.Handler below the given prefix.

func (*App) OnShutdown

func (a *App) OnShutdown(fn ShutdownHook) *App

OnShutdown registers a shutdown hook.

func (*App) Options

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

Options registers an OPTIONS route for the given pattern.

func (*App) Patch

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

Patch registers a PATCH route for the given pattern.

func (*App) Post

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

Post registers a POST route for the given pattern.

func (*App) Put

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

Put registers a PUT route for the given pattern.

func (*App) Register

func (a *App) Register(plugin Plugin, opts ...PluginOption) *App

Register registers a plugin with the framework.

func (*App) ReleaseContext

func (a *App) ReleaseContext(c *Context)

ReleaseContext returns a Context to the pool.

func (*App) Routes

func (a *App) Routes() []RouteInfo

Routes returns the registered route metadata in registration order.

func (*App) ServeHTTP

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler for the application.

func (*App) SetMethodNotAllowedHandler

func (a *App) SetMethodNotAllowedHandler(h HandlerFunc) *App

SetMethodNotAllowedHandler replaces the default 405 handler used for method mismatches.

func (*App) SetNotFoundHandler

func (a *App) SetNotFoundHandler(h HandlerFunc) *App

SetNotFoundHandler replaces the default 404 handler used for unmatched routes.

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the server.

func (*App) Use

func (a *App) Use(middlewares ...Middleware) *App

Use appends middleware to the global middleware chain.

type AppError

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

AppError is a structured HTTP error with status code, machine-readable code, and message.

func ErrBadGateway

func ErrBadGateway(msg string) *AppError

ErrBadGateway creates a 502 bad gateway AppError.

func ErrBadRequest

func ErrBadRequest(msg string) *AppError

ErrBadRequest creates a 400 bad request AppError.

func ErrConflict

func ErrConflict(msg string) *AppError

ErrConflict creates a 409 conflict AppError.

func ErrForbidden

func ErrForbidden(msg string) *AppError

ErrForbidden creates a 403 forbidden AppError.

func ErrGatewayTimeout

func ErrGatewayTimeout(msg string) *AppError

ErrGatewayTimeout creates a 504 gateway timeout AppError.

func ErrInternal

func ErrInternal(err error) *AppError

ErrInternal creates a 500 internal server error AppError.

func ErrMethodNotAllowed

func ErrMethodNotAllowed(msg string) *AppError

ErrMethodNotAllowed creates a 405 method not allowed AppError.

func ErrNotFound

func ErrNotFound(msg string) *AppError

ErrNotFound creates a 404 not found AppError.

func ErrServiceUnavailable

func ErrServiceUnavailable(msg string) *AppError

ErrServiceUnavailable creates a 503 service unavailable AppError.

func ErrTooManyRequests

func ErrTooManyRequests(msg string) *AppError

ErrTooManyRequests creates a 429 rate limit AppError.

func ErrUnauthorized

func ErrUnauthorized(msg string) *AppError

ErrUnauthorized creates a 401 unauthorized AppError.

func ErrUnprocessable

func ErrUnprocessable(msg string) *AppError

ErrUnprocessable creates a 422 validation failure AppError.

func NewError

func NewError(status int, code, message string) *AppError

NewError creates a custom AppError.

func (*AppError) Code

func (e *AppError) Code() string

Code returns the machine-readable error code.

func (*AppError) Detail

func (e *AppError) Detail() string

Detail returns the optional detail string included with the error.

func (*AppError) Error

func (e *AppError) Error() string

func (*AppError) Internal

func (e *AppError) Internal() error

Internal returns the wrapped internal error, if any.

func (*AppError) Message

func (e *AppError) Message() string

Message returns the client-facing error message.

func (*AppError) StatusCode

func (e *AppError) StatusCode() int

StatusCode returns the HTTP status code associated with the error.

func (*AppError) Unwrap

func (e *AppError) Unwrap() error

Unwrap returns the wrapped internal error for errors.Is and errors.As.

func (*AppError) WithDetail

func (e *AppError) WithDetail(detail string) *AppError

WithDetail sets a detail string on the error and returns the same value.

func (*AppError) WithInternal

func (e *AppError) WithInternal(err error) *AppError

WithInternal attaches an internal error that is not serialized to clients.

type BindError

type BindError struct {
	// Err is the underlying binding failure.
	Err error
	// Source identifies the binding stage that failed, such as "binding" or "body".
	Source string
}

BindError represents an error during request binding.

func (*BindError) Error

func (e *BindError) Error() string

Error returns the formatted binding error string.

func (*BindError) Unwrap

func (e *BindError) Unwrap() error

Unwrap returns the underlying binding error.

type Codec

type Codec interface {
	// Decode reads from r and unmarshals into v (stream-based, for request bodies).
	Decode(r io.Reader, v any) error
	// Encode marshals v and writes to w (stream-based, for response bodies).
	Encode(w io.Writer, v any) error
	// UnmarshalBytes unmarshals pre-read bytes into v (for cached/small payloads).
	UnmarshalBytes(data []byte, v any) error
	// MarshalBytes marshals v into bytes (for pre-serialization).
	MarshalBytes(v any) ([]byte, error)
	// ContentType returns the MIME type for this codec.
	ContentType() string
}

Codec defines the interface for encoding/decoding request and response bodies.

type Config

type Config struct {
	// ReadTimeout is the maximum duration for reading the entire request.
	ReadTimeout time.Duration
	// ReadHeaderTimeout is the maximum duration for reading request headers.
	ReadHeaderTimeout time.Duration
	// WriteTimeout is the maximum duration before timing out response writes.
	WriteTimeout time.Duration
	// IdleTimeout is the maximum keep-alive idle time between requests.
	IdleTimeout time.Duration
	// ShutdownTimeout is the maximum time allowed for graceful shutdown.
	ShutdownTimeout time.Duration
	// MaxHeaderBytes limits the size of incoming request headers.
	MaxHeaderBytes int
	// MaxBodySize is the default request body limit applied by the framework.
	MaxBodySize int64
	// TLSConfig provides the TLS configuration used by HTTPS listeners.
	TLSConfig *tls.Config
	// TrustedProxies contains CIDRs or IPs whose forwarding headers are trusted.
	TrustedProxies []string
	// DisableHTTP2 forces HTTPS listeners to serve HTTP/1.1 only.
	DisableHTTP2 bool
	// Banner controls whether the startup banner is printed.
	Banner bool
	// Debug enables framework-level debug behavior where supported.
	Debug bool
	// RedirectTrailingSlash enables redirects between slash and non-slash route variants.
	RedirectTrailingSlash bool
	// RequestContextBridge clones requests to keep Aarv Context available through
	// raw r.WithContext(...) middleware chains. Disable only for fully opt-in
	// performance-sensitive stacks that do not need that compatibility.
	RequestContextBridge bool
}

Config holds server configuration values.

type Context

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

Context wraps the http.Request and http.ResponseWriter with convenience helpers. It is pooled via sync.Pool — do NOT hold references to it beyond the handler lifetime.

func FromRequest

func FromRequest(r *http.Request) (*Context, bool)

FromRequest extracts the aarv Context from an http.Request. This is exported so sub-packages (plugins) can access the aarv Context.

func (*Context) AddHeader

func (c *Context) AddHeader(name, value string)

AddHeader adds a response header value.

func (*Context) Attachment

func (c *Context) Attachment(filepath, filename string) error

Attachment sends a file as an attachment (download).

func (*Context) Bind

func (c *Context) Bind(dest any) error

Bind decodes the request body into dest using the configured codec.

func (*Context) BindForm

func (c *Context) BindForm(dest any) error

BindForm decodes form data into dest.

func (*Context) BindJSON

func (c *Context) BindJSON(dest any) error

BindJSON decodes the JSON request body into dest.

func (*Context) BindQuery

func (c *Context) BindQuery(dest any) error

BindQuery decodes query parameters into a struct using the query struct tag.

func (*Context) Blob

func (c *Context) Blob(status int, contentType string, data []byte) error

Blob writes raw bytes with the given content type.

func (*Context) Body

func (c *Context) Body() ([]byte, error)

Body reads and caches the request body bytes. Subsequent calls return cached data.

func (*Context) Context

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

Context returns the request's context.Context.

func (*Context) Cookie

func (c *Context) Cookie(name string) (*http.Cookie, error)

Cookie returns a request cookie by name.

func (*Context) Error

func (c *Context) Error(status int, message string) error

Error is a shortcut to return an AppError from a handler.

func (*Context) ErrorWithDetail

func (c *Context) ErrorWithDetail(status int, message, detail string) error

ErrorWithDetail returns an AppError with a detail string.

func (*Context) File

func (c *Context) File(filepath string) error

File sends a file as the response.

func (*Context) FormFile

func (c *Context) FormFile(name string) (*multipart.FileHeader, error)

FormFile returns the first file for the given form key.

func (*Context) Get

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

Get retrieves a value from the request-scoped store.

func (*Context) HTML

func (c *Context) HTML(status int, html string) error

HTML writes an HTML response.

func (*Context) Header

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

Header returns a request header value.

func (*Context) HeaderValues

func (c *Context) HeaderValues(name string) []string

HeaderValues returns all values for a request header.

func (*Context) HookError added in v0.4.0

func (c *Context) HookError() error

HookError returns the currently propagated lifecycle error for OnError hooks. It is only set while the framework is invoking OnError.

func (*Context) Host

func (c *Context) Host() string

Host returns the request host.

func (*Context) IsTLS

func (c *Context) IsTLS() bool

IsTLS returns true if the request was served over TLS.

func (*Context) JSON

func (c *Context) JSON(status int, v any) error

JSON serializes v as JSON and writes it with the given status code. If status is 0, uses the status set by Status() or defaults to 200.

func (*Context) JSONPretty

func (c *Context) JSONPretty(status int, v any) error

JSONPretty serializes v as indented JSON.

func (*Context) Logger

func (c *Context) Logger() *slog.Logger

Logger returns a request-scoped logger with the request ID attached (cached).

func (*Context) Method

func (c *Context) Method() string

Method returns the HTTP method.

func (*Context) MustGet

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

MustGet retrieves a value from the store or panics if missing.

func (*Context) NoContent

func (c *Context) NoContent(status int) error

NoContent sends a response with no body.

func (*Context) Param

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

Param returns a path parameter by name.

func (*Context) ParamInt

func (c *Context) ParamInt(name string) (int, error)

ParamInt returns a path parameter parsed as int.

func (*Context) ParamInt64

func (c *Context) ParamInt64(name string) (int64, error)

ParamInt64 returns a path parameter parsed as int64.

func (*Context) ParamUUID

func (c *Context) ParamUUID(name string) (string, error)

ParamUUID returns a path parameter validated as UUID format.

func (*Context) Path

func (c *Context) Path() string

Path returns the URL path.

func (*Context) Protocol

func (c *Context) Protocol() string

Protocol returns the protocol version string (e.g. "HTTP/2.0").

func (*Context) Query

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

Query returns a query parameter by name.

func (*Context) QueryBool

func (c *Context) QueryBool(name string, fallback bool) bool

QueryBool returns a query parameter parsed as bool, with a fallback.

func (*Context) QueryDefault

func (c *Context) QueryDefault(name, fallback string) string

QueryDefault returns a query parameter or a fallback value.

func (*Context) QueryFloat64

func (c *Context) QueryFloat64(name string, fallback float64) float64

QueryFloat64 returns a query parameter parsed as float64, with a fallback.

func (*Context) QueryInt

func (c *Context) QueryInt(name string, fallback int) int

QueryInt returns a query parameter parsed as int, with a fallback.

func (*Context) QueryInt64

func (c *Context) QueryInt64(name string, fallback int64) int64

QueryInt64 returns a query parameter parsed as int64, with a fallback.

func (*Context) QueryParams

func (c *Context) QueryParams() url.Values

QueryParams returns all query parameters.

func (*Context) QuerySlice

func (c *Context) QuerySlice(name string) []string

QuerySlice returns all values for a query parameter.

func (*Context) RealIP

func (c *Context) RealIP() string

RealIP extracts the client IP, respecting X-Real-IP and X-Forwarded-For headers. It only trusts proxy headers if the direct client IP is in the TrustedProxies list.

func (*Context) Redirect

func (c *Context) Redirect(status int, url string) error

Redirect sends an HTTP redirect.

func (*Context) Request

func (c *Context) Request() *http.Request

Request returns the underlying *http.Request.

func (*Context) RequestID

func (c *Context) RequestID() string

RequestID returns the request ID from the store (set by RequestID middleware).

func (*Context) Response

func (c *Context) Response() http.ResponseWriter

Response returns the underlying http.ResponseWriter.

func (*Context) Scheme

func (c *Context) Scheme() string

Scheme returns "https" or "http".

func (*Context) SendStatus

func (c *Context) SendStatus(code int) error

SendStatus writes only the status code with no body (alias for NoContent).

func (*Context) Set

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

Set stores a key-value pair in the request-scoped store.

func (*Context) SetContext

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

SetContext replaces the request's context.

func (*Context) SetContextValue added in v0.4.0

func (c *Context) SetContextValue(key, value any)

SetContextValue stores a value in the request context while preserving Aarv's own context marker in a single wrapped context object.

func (*Context) SetCookie

func (c *Context) SetCookie(cookie *http.Cookie)

SetCookie sets a response cookie.

func (*Context) SetHeader

func (c *Context) SetHeader(name, value string)

SetHeader sets a response header.

func (*Context) SetResponse added in v0.4.0

func (c *Context) SetResponse(w http.ResponseWriter)

SetResponse replaces the underlying response writer.

func (*Context) Status

func (c *Context) Status(code int) *Context

Status sets the response status code for chaining. Use with JSON, Text, etc. to set status before writing. Example: c.Status(201).JSON(data)

func (*Context) Stream

func (c *Context) Stream(status int, contentType string, reader io.Reader) error

Stream copies from reader directly to the response writer. It bypasses the buffered response writer for streaming responses.

func (*Context) Text

func (c *Context) Text(status int, text string) error

Text writes a plain text response.

func (*Context) Written

func (c *Context) Written() bool

Written returns true if a response has already been written.

func (*Context) XML

func (c *Context) XML(status int, v any) error

XML serializes v as XML.

type CustomBinder

type CustomBinder interface {
	BindFromContext(c *Context) error
}

CustomBinder is an interface for types that can bind themselves from the request context. If a type implements this interface, BindFromContext is called instead of the default binding.

type CustomRuleFunc

type CustomRuleFunc func(field reflect.Value, param string) bool

CustomRuleFunc is a function signature for custom validation rules. The function receives the field value and the rule parameter, and returns true if valid.

type ErrorHandler

type ErrorHandler func(c *Context, err error)

ErrorHandler is a function that handles errors returned by handlers.

type HandlerFunc

type HandlerFunc func(*Context) error

HandlerFunc is the framework's handler signature — every handler converts to this.

func Adapt

func Adapt(fn func(http.ResponseWriter, *http.Request)) HandlerFunc

Adapt wraps a stdlib http.HandlerFunc as a framework HandlerFunc.

func Bind

func Bind[Req any, Res any](fn func(*Context, Req) (Res, error)) HandlerFunc

Bind creates a typed handler with automatic request parsing and response serialization. At registration time, it pre-computes the binder and validator for Req. At request time, it decodes the request into Req, validates it, calls the handler, and serializes the Res as JSON.

func BindReq

func BindReq[Req any](fn func(*Context, Req) error) HandlerFunc

BindReq creates a handler with request parsing but manual response writing.

func BindRes

func BindRes[Res any](fn func(*Context) (Res, error)) HandlerFunc

BindRes creates a handler with automatic response serialization but no request parsing.

type HookFunc

type HookFunc func(c *Context) error

HookFunc is a lifecycle hook function.

type HookPhase

type HookPhase int

HookPhase represents a phase in the request lifecycle.

const (
	// OnRequest runs immediately after the framework acquires the request context.
	OnRequest HookPhase = iota
	// PreRouting is reserved for hooks that should run before route matching.
	PreRouting
	// PreParsing is reserved for hooks that should run before body parsing.
	PreParsing
	// PreValidation is reserved for hooks that should run after parsing and before validation.
	PreValidation
	// PreHandler is reserved for hooks that should run after validation and before the handler.
	PreHandler
	// OnResponse runs after the handler completes and before the final response lifecycle ends.
	OnResponse
	// OnSend runs just before buffered response bytes are flushed to the client.
	OnSend
	// OnError runs when the framework handles an error returned from the chain.
	OnError
	// OnStartup runs before the server begins accepting requests.
	OnStartup
	// OnShutdown runs when graceful shutdown starts.
	OnShutdown
)

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware is the standard Go middleware signature.

func Logger

func Logger() Middleware

Logger returns a middleware that logs requests using slog.

func Recovery

func Recovery() Middleware

Recovery returns a middleware that recovers from panics.

func RegisterNativeMiddleware added in v0.4.0

func RegisterNativeMiddleware(m Middleware, fn MiddlewareFunc) Middleware

RegisterNativeMiddleware associates an Aarv-native middleware implementation with a standard net/http middleware. It enables the runtime to use a faster native exact-route path when every middleware in the chain provides one.

func WrapMiddleware

func WrapMiddleware(fn MiddlewareFunc) Middleware

WrapMiddleware converts a framework MiddlewareFunc to a stdlib Middleware.

type MiddlewareFunc

type MiddlewareFunc func(next HandlerFunc) HandlerFunc

MiddlewareFunc is a framework-specific middleware with access to Context.

type OptimizedJSONCodec

type OptimizedJSONCodec = StdJSONCodec

OptimizedJSONCodec is kept as a deprecated alias for backward compatibility. Deprecated: use StdJSONCodec or NewStdJSONCodec.

func NewOptimizedJSONCodec

func NewOptimizedJSONCodec() *OptimizedJSONCodec

NewOptimizedJSONCodec is kept as a deprecated constructor alias. Deprecated: use NewStdJSONCodec.

type Option

type Option func(*App)

Option configures the App.

func WithBanner

func WithBanner(enabled bool) Option

WithBanner enables or disables the startup banner.

func WithCodec

func WithCodec(codec Codec) Option

WithCodec sets the JSON codec.

func WithDebug

func WithDebug(enabled bool) Option

WithDebug enables verbose debug logging.

func WithDisableHTTP2

func WithDisableHTTP2(disabled bool) Option

WithDisableHTTP2 disables HTTP/2.

func WithErrorHandler

func WithErrorHandler(fn ErrorHandler) Option

WithErrorHandler sets a custom error handler.

func WithIdleTimeout

func WithIdleTimeout(d time.Duration) Option

WithIdleTimeout sets the server idle timeout.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the structured logger.

func WithMaxBodySize

func WithMaxBodySize(n int64) Option

WithMaxBodySize sets the global max body size.

func WithMaxHeaderBytes

func WithMaxHeaderBytes(n int) Option

WithMaxHeaderBytes sets the max header bytes.

func WithReadHeaderTimeout

func WithReadHeaderTimeout(d time.Duration) Option

WithReadHeaderTimeout sets the server read header timeout.

func WithReadTimeout

func WithReadTimeout(d time.Duration) Option

WithReadTimeout sets the server read timeout.

func WithRedirectTrailingSlash

func WithRedirectTrailingSlash(enabled bool) Option

WithRedirectTrailingSlash enables trailing slash redirect.

func WithRequestContextBridge added in v0.4.0

func WithRequestContextBridge(enabled bool) Option

WithRequestContextBridge controls whether Aarv clones requests to keep the framework Context attached through raw r.WithContext(...) middleware chains. Disable it only for middleware stacks that never rely on aarv.FromRequest(...) after cloning requests, in exchange for a slightly cheaper hot path.

func WithShutdownTimeout

func WithShutdownTimeout(d time.Duration) Option

WithShutdownTimeout sets the graceful shutdown timeout.

func WithTLSConfig

func WithTLSConfig(cfg *tls.Config) Option

WithTLSConfig sets a custom TLS configuration.

func WithTrustedProxies

func WithTrustedProxies(cidrs ...string) Option

WithTrustedProxies sets the trusted proxy CIDRs for IP extraction.

func WithWriteTimeout

func WithWriteTimeout(d time.Duration) Option

WithWriteTimeout sets the server write timeout.

type ParamParser

type ParamParser interface {
	ParseParam(value string) error
}

ParamParser is an interface for types that can parse themselves from a string parameter. This allows custom types to be used as path parameters, query params, etc.

type Plugin

type Plugin interface {
	Name() string
	Version() string
	Register(app *PluginContext) error
}

Plugin is the interface for framework plugins. All plugins must implement Name(), Version(), and Register().

type PluginContext

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

PluginContext is a scoped view of the App given to plugins during registration.

func (*PluginContext) AddHook

func (pc *PluginContext) AddHook(phase HookPhase, fn HookFunc)

AddHook adds a lifecycle hook from this plugin.

func (*PluginContext) App

func (pc *PluginContext) App() *App

App returns the underlying App (for advanced use).

func (*PluginContext) Decorate

func (pc *PluginContext) Decorate(key string, value any)

Decorate registers a shared service by key.

func (*PluginContext) Delete

func (pc *PluginContext) Delete(pattern string, handler any, opts ...RouteOption) *PluginContext

Delete registers a DELETE route scoped to this plugin.

func (*PluginContext) Get

func (pc *PluginContext) Get(pattern string, handler any, opts ...RouteOption) *PluginContext

Get registers a GET route scoped to this plugin.

func (*PluginContext) Group

func (pc *PluginContext) Group(prefix string, fn func(g *RouteGroup)) *PluginContext

Group creates a nested route group within the plugin.

func (*PluginContext) Logger

func (pc *PluginContext) Logger() *slog.Logger

Logger returns the plugin-scoped logger.

func (*PluginContext) Post

func (pc *PluginContext) Post(pattern string, handler any, opts ...RouteOption) *PluginContext

Post registers a POST route scoped to this plugin.

func (*PluginContext) Put

func (pc *PluginContext) Put(pattern string, handler any, opts ...RouteOption) *PluginContext

Put registers a PUT route scoped to this plugin.

func (*PluginContext) Register

func (pc *PluginContext) Register(plugin Plugin) error

Register registers a nested plugin.

func (*PluginContext) Resolve

func (pc *PluginContext) Resolve(key string) (any, bool)

Resolve retrieves a decorated service by key.

func (*PluginContext) Use

func (pc *PluginContext) Use(middlewares ...Middleware) *PluginContext

Use adds middleware scoped to this plugin's routes.

type PluginFunc

type PluginFunc func(app *PluginContext) error

PluginFunc adapts a function to the Plugin interface.

func (PluginFunc) Name

func (f PluginFunc) Name() string

Name returns the default plugin name for a PluginFunc adapter.

func (PluginFunc) Register

func (f PluginFunc) Register(app *PluginContext) error

Register invokes the adapted plugin function.

func (PluginFunc) Version

func (f PluginFunc) Version() string

Version returns the default plugin version for a PluginFunc adapter.

type PluginOption

type PluginOption func(*string)

PluginOption configures plugin registration.

func WithPrefix

func WithPrefix(prefix string) PluginOption

WithPrefix sets the plugin's route prefix.

type PluginWithDeps

type PluginWithDeps interface {
	Plugin
	Dependencies() []string
}

PluginWithDeps is an optional interface for plugins that declare dependencies.

type RouteGroup

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

RouteGroup represents a group of routes with a common prefix and middleware.

func (*RouteGroup) Any

func (g *RouteGroup) Any(pattern string, handler any, opts ...RouteOption) *RouteGroup

Any registers the handler for the common HTTP methods within the group.

func (*RouteGroup) Delete

func (g *RouteGroup) Delete(pattern string, handler any, opts ...RouteOption) *RouteGroup

Delete registers a DELETE route within the group.

func (*RouteGroup) Get

func (g *RouteGroup) Get(pattern string, handler any, opts ...RouteOption) *RouteGroup

Get registers a GET route within the group.

func (*RouteGroup) Group

func (g *RouteGroup) Group(prefix string, fn func(g *RouteGroup)) *RouteGroup

Group creates a nested route group under the current group's prefix.

func (*RouteGroup) Head

func (g *RouteGroup) Head(pattern string, handler any, opts ...RouteOption) *RouteGroup

Head registers a HEAD route within the group.

func (*RouteGroup) Options

func (g *RouteGroup) Options(pattern string, handler any, opts ...RouteOption) *RouteGroup

Options registers an OPTIONS route within the group.

func (*RouteGroup) Patch

func (g *RouteGroup) Patch(pattern string, handler any, opts ...RouteOption) *RouteGroup

Patch registers a PATCH route within the group.

func (*RouteGroup) Post

func (g *RouteGroup) Post(pattern string, handler any, opts ...RouteOption) *RouteGroup

Post registers a POST route within the group.

func (*RouteGroup) Put

func (g *RouteGroup) Put(pattern string, handler any, opts ...RouteOption) *RouteGroup

Put registers a PUT route within the group.

func (*RouteGroup) Use

func (g *RouteGroup) Use(middlewares ...Middleware) *RouteGroup

Use appends middleware scoped to routes registered on this group.

type RouteInfo

type RouteInfo struct {
	// Method is the HTTP method registered for the route.
	Method string `json:"method"`
	// Pattern is the path pattern registered for the route.
	Pattern string `json:"pattern"`
	// Name is the optional application-defined route name.
	Name string `json:"name,omitempty"`
	// Tags contains optional route classification tags.
	Tags []string `json:"tags,omitempty"`
	// Description is the optional long-form route description.
	Description string `json:"description,omitempty"`
	// Deprecated reports whether the route is marked deprecated.
	Deprecated bool `json:"deprecated,omitempty"`
}

RouteInfo describes a registered route for introspection.

type RouteOption

type RouteOption func(*routeConfig)

RouteOption configures per-route metadata and behavior.

func WithDeprecated

func WithDeprecated() RouteOption

WithDeprecated marks the route as deprecated in route metadata.

func WithDescription

func WithDescription(desc string) RouteOption

WithDescription sets the long-form description for the route.

func WithName

func WithName(name string) RouteOption

WithName sets a stable human-readable name for the route.

func WithOperationID

func WithOperationID(id string) RouteOption

WithOperationID sets a machine-readable identifier for the route.

func WithRouteMaxBodySize

func WithRouteMaxBodySize(bytes int64) RouteOption

WithRouteMaxBodySize overrides the global body limit for this route.

func WithRouteMiddleware

func WithRouteMiddleware(mw ...Middleware) RouteOption

WithRouteMiddleware attaches middleware that runs only for this route.

func WithSummary

func WithSummary(s string) RouteOption

WithSummary sets a short summary for the route.

func WithTags

func WithTags(tags ...string) RouteOption

WithTags associates one or more tags with the route.

type SelfValidator

type SelfValidator interface {
	Validate() []ValidationError
}

SelfValidator can be implemented by types to provide custom validation.

type ShutdownHook

type ShutdownHook func(ctx interface{ Done() <-chan struct{} }) error

ShutdownHook runs during graceful shutdown with the shutdown context.

type StdJSONCodec

type StdJSONCodec struct{}

StdJSONCodec implements the canonical stdlib-backed JSON codec. It uses encoding/json and a pooled buffer for MarshalBytes.

func NewStdJSONCodec added in v0.4.0

func NewStdJSONCodec() *StdJSONCodec

NewStdJSONCodec returns the canonical stdlib-backed JSON codec.

func (StdJSONCodec) ContentType

func (StdJSONCodec) ContentType() string

ContentType returns the MIME type produced by StdJSONCodec.

func (StdJSONCodec) Decode

func (StdJSONCodec) Decode(r io.Reader, v any) error

Decode reads JSON from r into v using encoding/json.

func (StdJSONCodec) Encode

func (StdJSONCodec) Encode(w io.Writer, v any) error

Encode writes v to w as JSON using encoding/json.

func (StdJSONCodec) MarshalBytes

func (StdJSONCodec) MarshalBytes(v any) ([]byte, error)

MarshalBytes encodes v to JSON bytes using a pooled buffer.

func (StdJSONCodec) UnmarshalBytes

func (StdJSONCodec) UnmarshalBytes(data []byte, v any) error

UnmarshalBytes decodes JSON bytes into v using encoding/json.

type StructLevelFunc

type StructLevelFunc func(v any) []ValidationError

StructLevelFunc is a function that performs struct-level validation.

type StructLevelValidator

type StructLevelValidator interface {
	ValidateStruct() []ValidationError
}

StructLevelValidator can be implemented by types to provide struct-level validation that runs after field validation.

type TestClient

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

TestClient provides a fluent API for testing aarv handlers without starting a server.

func NewTestClient

func NewTestClient(app *App) *TestClient

NewTestClient creates a TestClient for the given App.

func (*TestClient) Delete

func (tc *TestClient) Delete(path string) *TestResponse

Delete sends a DELETE request.

func (*TestClient) Do

func (tc *TestClient) Do(req *http.Request) *TestResponse

Do sends a custom http.Request.

func (*TestClient) Get

func (tc *TestClient) Get(path string) *TestResponse

Get sends a GET request.

func (*TestClient) Patch

func (tc *TestClient) Patch(path string, body any) *TestResponse

Patch sends a PATCH request with a JSON body.

func (*TestClient) Post

func (tc *TestClient) Post(path string, body any) *TestResponse

Post sends a POST request with a JSON body.

func (*TestClient) Put

func (tc *TestClient) Put(path string, body any) *TestResponse

Put sends a PUT request with a JSON body.

func (*TestClient) WithBearer

func (tc *TestClient) WithBearer(token string) *TestClient

WithBearer adds an Authorization: Bearer header.

func (*TestClient) WithCookie

func (tc *TestClient) WithCookie(cookie *http.Cookie) *TestClient

WithCookie adds a cookie to the test request.

func (*TestClient) WithHeader

func (tc *TestClient) WithHeader(key, value string) *TestClient

WithHeader adds a header to the test request.

func (*TestClient) WithQuery

func (tc *TestClient) WithQuery(key, value string) *TestClient

WithQuery adds a query parameter.

type TestResponse

type TestResponse struct {
	// Status is the recorded HTTP status code.
	Status int
	// Headers contains the recorded response headers.
	Headers http.Header
	// Body contains the recorded response body bytes.
	Body []byte
}

TestResponse wraps an httptest.ResponseRecorder result.

func (*TestResponse) AssertStatus

func (tr *TestResponse) AssertStatus(t *testing.T, expected int)

AssertStatus checks that the response status matches expected.

func (*TestResponse) JSON

func (tr *TestResponse) JSON(dest any) error

JSON unmarshals the response body into dest.

func (*TestResponse) Text

func (tr *TestResponse) Text() string

Text returns the body as a string.

type ValidationError

type ValidationError struct {
	// Field is the field or parameter name that failed validation.
	Field string `json:"field"`
	// Tag is the validation rule that failed.
	Tag string `json:"tag"`
	// Param is the optional validation rule parameter.
	Param string `json:"param,omitempty"`
	// Value is the rejected value when it is safe to include.
	Value any `json:"value,omitempty"`
	// Message is the human-readable validation message.
	Message string `json:"message"`
}

ValidationError represents a single field validation failure.

type ValidationErrors

type ValidationErrors struct {
	// Errors contains the individual validation failures.
	Errors []ValidationError `json:"details"`
}

ValidationErrors is a collection of validation failures.

func (*ValidationErrors) Error

func (e *ValidationErrors) Error() string

Error returns a summary string for the validation failure set.

type ValidationMessageFunc added in v0.4.0

type ValidationMessageFunc func(field, param string) string

ValidationMessageFunc customizes the human-readable message for a failed rule.

Directories

Path Synopsis
codec
segmentio module
examples
auth command
Example: Authentication patterns — JWT, API keys, and session-based auth.
Example: Authentication patterns — JWT, API keys, and session-based auth.
binding command
codec command
Example: Pluggable Codec — demonstrates the pluggable Codec interface.
Example: Pluggable Codec — demonstrates the pluggable Codec interface.
custom-plugin command
Example: Writing a custom plugin — demonstrates the Plugin interface, PluginContext methods, lifecycle hooks, decorated services, and scoped route registration.
Example: Writing a custom plugin — demonstrates the Plugin interface, PluginContext methods, lifecycle hooks, decorated services, and scoped route registration.
database command
Example: Database integration patterns — demonstrates common patterns for integrating databases with aarv, using an in-memory store that mimics real database patterns (connection pooling, transactions, etc.).
Example: Database integration patterns — demonstrates common patterns for integrating databases with aarv, using an in-memory store that mimics real database patterns (connection pooling, transactions, etc.).
encrypt command
Example: AES-GCM Encrypted API
Example: AES-GCM Encrypted API
error-handling command
fileserver command
Example: File upload, download, and static file serving.
Example: File upload, download, and static file serving.
hello command
hooks command
Example: Lifecycle hooks — demonstrates all hook phases, priorities, shutdown hooks, and OnError handling.
Example: Lifecycle hooks — demonstrates all hook phases, priorities, shutdown hooks, and OnError handling.
json-logger command
Example: JSON Structured Logging with Full Request/Response Dump
Example: JSON Structured Logging with Full Request/Response Dump
middleware-chain command
Example: Middleware chain showcasing all built-in plugins.
Example: Middleware chain showcasing all built-in plugins.
rest-crud command
Example: REST CRUD API with typed handlers, validation, path params, query binding, error handling, route groups, and middleware.
Example: REST CRUD API with typed handlers, validation, path params, query binding, error handling, route groups, and middleware.
route-groups command
streaming command
Example: Server-Sent Events (SSE) and streaming responses.
Example: Server-Sent Events (SSE) and streaming responses.
internal
plugins
bodylimit
Package bodylimit provides request body size limiting middleware for the aarv framework.
Package bodylimit provides request body size limiting middleware for the aarv framework.
compress
Package compress provides gzip and deflate compression middleware for the aarv framework.
Package compress provides gzip and deflate compression middleware for the aarv framework.
cors
Package cors provides Cross-Origin Resource Sharing (CORS) middleware for the aarv framework.
Package cors provides Cross-Origin Resource Sharing (CORS) middleware for the aarv framework.
encrypt
Package encrypt provides AES-GCM encryption middleware for the aarv framework.
Package encrypt provides AES-GCM encryption middleware for the aarv framework.
etag
Package etag provides ETag middleware for the aarv framework.
Package etag provides ETag middleware for the aarv framework.
health
Package health provides health check endpoint middleware for the aarv framework.
Package health provides health check endpoint middleware for the aarv framework.
logger
Package logger provides request logging middleware for the aarv framework.
Package logger provides request logging middleware for the aarv framework.
recover
Package recover provides panic recovery middleware for the aarv framework.
Package recover provides panic recovery middleware for the aarv framework.
requestid
Package requestid provides request ID middleware for the aarv framework.
Package requestid provides request ID middleware for the aarv framework.
secure
Package secure provides security headers middleware for the aarv framework.
Package secure provides security headers middleware for the aarv framework.
static
Package static provides static file serving middleware for the aarv framework.
Package static provides static file serving middleware for the aarv framework.
timeout
Package timeout provides request timeout middleware for the aarv framework.
Package timeout provides request timeout middleware for the aarv framework.
verboselog
Package verboselog provides full request/response logging middleware for the aarv framework.
Package verboselog provides full request/response logging middleware for the aarv framework.

Jump to

Keyboard shortcuts

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