aku

package module
v0.0.0-...-2a7ffba Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2026 License: MIT Imports: 22 Imported by: 0

README

Aku

[!IMPORTANT] Aku is a high-performance, typesafe web framework for Go 1.22+ designed specifically for building APIs.

Aku bridges the gap between the standard library's net/http and the ergonomics of modern frameworks like FastAPI or Axum. It uses Go's type system to automate request extraction, validation, and documentation without sacrificing compatibility.

Features

  • Standard Library First: Built on Go 1.22+ http.ServeMux. Pure http.Handler compatibility.
  • Typesafe Extraction: Automatically map Path, Query, Header, Form, and Body into a single request struct.
  • Zero-Reflect Hot Path: Reflection is used at registration time to "compile" extraction plans; the request path is optimized for performance.
  • Automatic OpenAPI 3.0: Generates documentation, including schemas and security requirements, from your Go types.
  • Validation: Built-in support for go-playground/validator tags and explicit Validate() error hooks.
  • Streaming & SSE: First-class support for io.Reader streaming and Server-Sent Events.
  • Middleware Suite: Production-ready Recover, Timeout, and CORS implementations.
  • Integration Testing: The repo's integration suite uses chainable helpers to keep API assertions readable.

Performance

Aku is designed with a Zero-Allocation Philosophy. By leveraging Go's reflection only at route registration time, Aku "compiles" static extraction plans for every handler. At runtime, the request path uses these pre-compiled plans and sync.Pool to achieve performance that is nearly identical to hand-optimized net/http code.

  • Pre-compiled Extraction: No reflection in the request hot path.
  • Buffer & Struct Reuse: Extensive use of sync.Pool to minimize GC pressure.
  • Standard Library Speed: Built directly on http.ServeMux with minimal wrapping.

Benchmarks consistently show Aku adds minimal overhead (~100ns) compared to manually binding net/http handlers. See benchmark_test.go for the latest verified results.

Quick Start

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/nijaru/aku"
)

type GreetRequest struct {
	Path struct {
		Name string `path:"name"`
	}
	Query struct {
		Shout bool `query:"shout"`
	}
}

type GreetResponse struct {
	Message string `json:"message"`
}

func Greet(ctx context.Context, in GreetRequest) (GreetResponse, error) {
	msg := "Hello, " + in.Path.Name
	if in.Query.Shout {
		msg += "!"
	}
	return GreetResponse{Message: msg}, nil
}

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

	// Register a route
	aku.Get(app, "/greet/{name}", Greet)

	// Serve OpenAPI UI at /docs
	app.OpenAPI("/openapi.json", "My API", "1.0.0")
	app.SwaggerUI("/docs", "/openapi.json")

	log.Println("Serving on :8080")
	log.Fatal(http.ListenAndServe(":8080", app))
}

Development

Use the repo-local hook setup to keep Go formatting out of commits:

make hooks

That configures Git to run .githooks/pre-commit, which formats staged Go files before the commit is created.

Useful local checks:

  • make fmt to rewrite tracked Go files in place
  • make fmt-check to verify formatting without changing files
  • make check to run formatting, tests, and the build

Request Extraction

Aku uses struct sections to define where data comes from. Each section is optional.

type CreateProductRequest struct {
	Header struct {
		IDPToken string `header:"X-IDP-Token"`
	}
	Path struct {
		Category string `path:"category"`
	}
	Query struct {
		Preview bool `query:"preview"`
	}
	Body struct {
		Name  string  `json:"name" validate:"required"`
		Price float64 `json:"price" validate:"gt=0"`
	}
}

Middleware

Use standard func(http.Handler) http.Handler middleware at the application or route level.

app := aku.New(
    aku.WithMiddleware(middleware.Recover, middleware.Logger),
)

aku.Post(app, "/secure", MyHandler, 
    aku.WithMiddleware(AuthMiddleware),
)

Standard Handler Escape Hatches

Aku keeps http.Handler compatibility for endpoints that do not need a typed request struct. HandleHTTP registers any standard handler with route metadata and middleware, while Metrics is a shorthand for read-only GET endpoints such as /metrics.

app.HandleHTTP(
    http.MethodGet,
    "/healthz",
    http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusNoContent)
    }),
    aku.WithSummary("Health check"),
)

app.Metrics("/metrics", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
}))

These routes still participate in application, group, and route middleware, and they still feed OpenAPI metadata.

Testing

Aku's integration tests live in tests/ and use repo-local helpers in internal/testutil to keep assertions concise.

That helper stays internal for now; the public API is the framework itself, not another testing abstraction. If you need to write your own Aku tests, use httptest directly or copy the patterns that fit your app.

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Delete

func Delete[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Delete registers a new DELETE route on the router.

func Get

func Get[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Get registers a new GET route on the router.

func Options

func Options[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Options registers a new OPTIONS route on the router.

func Patch

func Patch[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Patch registers a new PATCH route on the router.

func Post

func Post[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Post registers a new POST route on the router.

func Put

func Put[In any, Out any](
	r Router,
	pattern string,
	handler Handler[In, Out],
	opts ...RouteOption,
) error

Put registers a new PUT route on the router.

func WS

func WS[In any, Msg any](
	r Router,
	pattern string,
	handler WebsocketHandler[In, Msg],
	opts ...RouteOption,
) error

WS registers a typesafe websocket route on the application or group.

Types

type App

type App struct {
	MaxMultipartMemory int64
	ShutdownTimeout    time.Duration
	// contains filtered or unexported fields
}

App is the core framework application, wrapping a standard library HTTP multiplexer.

func New

func New(opts ...Option) *App

New creates a new Aku application.

func (*App) AddErrorObserver

func (a *App) AddErrorObserver(observer func(context.Context, error))

AddErrorObserver adds an error observer to the application. Error observers are called whenever an error is handled by the framework.

func (*App) AddSecurityScheme

func (a *App) AddSecurityScheme(name string, scheme SecurityScheme)

AddSecurityScheme adds a security scheme to the application.

func (*App) App

func (a *App) App() *App

func (*App) Group

func (a *App) Group(prefix string, mw ...func(http.Handler) http.Handler) *Group

Group creates a new route group with the given prefix and middleware.

func (*App) Handle

func (a *App) Handle(method, pattern string, handler http.Handler, route *Route)

Handle implements the Router interface.

func (*App) HandleHTTP

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

HandleHTTP registers a standard http.Handler on the application's multiplexer. This is useful for integrating third-party handlers like Prometheus or health checks that don't follow the typed Handler[In, Out] pattern. Route options such as middleware, status, tags, and security are still applied.

func (*App) Metrics

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

Metrics registers a standard http.Handler for serving metrics (e.g., Prometheus).

func (*App) Middleware

func (a *App) Middleware() []func(http.Handler) http.Handler

func (*App) OpenAPI

func (a *App) OpenAPI(pattern, title, version string)

OpenAPI registers an endpoint that serves the OpenAPI JSON specification.

func (*App) OpenAPIDocument

func (a *App) OpenAPIDocument(title, version string) *openapi.Document

OpenAPIDocument generates an OpenAPI 3.0 document for the application.

func (*App) OpenAPIHandler

func (a *App) OpenAPIHandler(title, version string) http.Handler

OpenAPIHandler returns an http.Handler that serves the OpenAPI JSON specification.

func (*App) Prefix

func (a *App) Prefix() string

func (*App) RedocUI

func (a *App) RedocUI(pattern, specURL string)

RedocUI registers an endpoint that serves the Redoc UI.

func (*App) RedocUIHandler

func (a *App) RedocUIHandler(specURL string) http.Handler

RedocUIHandler returns an http.Handler that serves the Redoc UI. The specURL is the URL where the OpenAPI JSON is served (e.g., "/openapi.json").

func (*App) Routes

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

Routes returns the list of registered routes and their metadata.

func (*App) Run

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

Run starts the HTTP server on the given address with graceful shutdown support. It listens for SIGINT and SIGTERM signals and waits for active requests to finish up to the configured ShutdownTimeout.

func (*App) ServeHTTP

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

func (*App) Static

func (a *App) Static(prefix, root string, opts ...RouteOption)

Static registers a directory of static files to be served at the given prefix.

func (*App) StaticFS

func (a *App) StaticFS(prefix string, fs http.FileSystem, opts ...RouteOption)

StaticFS registers a file system of static files to be served at the given prefix.

func (*App) SwaggerUI

func (a *App) SwaggerUI(pattern, specURL string)

SwaggerUI registers an endpoint that serves the Swagger UI.

func (*App) SwaggerUIHandler

func (a *App) SwaggerUIHandler(specURL string) http.Handler

SwaggerUIHandler returns an http.Handler that serves the Swagger UI. The specURL is the URL where the OpenAPI JSON is served (e.g., "/openapi.json").

func (*App) Use

func (a *App) Use(mw ...func(http.Handler) http.Handler)

Use adds global middleware to the application.

func (*App) WS

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

WS satisfies the Router interface for WebSockets.

type Binder

type Binder interface {
	UnmarshalAku(val string) error
}

Binder is the interface that can be implemented by types to customize how they are extracted from path, query, or header parameters.

type ContextKey

type ContextKey = bind.ContextKey

ContextKey is a custom type used for context value lookups to avoid collisions with built-in string types, satisfying standard go linters (e.g., SA1029).

type ErrorHandler

type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)

ErrorHandler is a function that handles errors returned by handlers or the framework.

type Event

type Event struct {
	ID    string
	Event string
	Data  any
}

Event represents a single Server-Sent Event.

type Group

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

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

func (*Group) App

func (g *Group) App() *App

func (*Group) Group

func (g *Group) Group(prefix string, mw ...func(http.Handler) http.Handler) *Group

Group creates a new sub-group from this group.

func (*Group) Handle

func (g *Group) Handle(method, pattern string, handler http.Handler, route *Route)

func (*Group) HandleHTTP

func (g *Group) HandleHTTP(method, pattern string, handler http.Handler, opts ...RouteOption)

HandleHTTP registers a standard http.Handler on the group's prefix.

func (*Group) Metrics

func (g *Group) Metrics(pattern string, handler http.Handler, opts ...RouteOption)

Metrics registers a standard http.Handler for serving metrics on the group's prefix.

func (*Group) Middleware

func (g *Group) Middleware() []func(http.Handler) http.Handler

func (*Group) Prefix

func (g *Group) Prefix() string

func (*Group) Static

func (g *Group) Static(prefix, root string, opts ...RouteOption)

func (*Group) StaticFS

func (g *Group) StaticFS(prefix string, fs http.FileSystem, opts ...RouteOption)

func (*Group) WS

func (g *Group) WS(pattern string, handler any, opts ...RouteOption) error

WS satisfies the Router interface for WebSockets.

type Handler

type Handler[In any, Out any] func(context.Context, In) (Out, error)

Handler is the canonical typed handler signature.

type Option

type Option func(*App)

Option configures an App instance.

func WithErrorHandler

func WithErrorHandler(h ErrorHandler) Option

WithErrorHandler sets a custom error handler for the application.

func WithGlobalMiddleware

func WithGlobalMiddleware(mw ...func(http.Handler) http.Handler) Option

WithGlobalMiddleware adds global middleware to the application.

func WithMaxMultipartMemory

func WithMaxMultipartMemory(max int64) Option

WithMaxMultipartMemory sets the maximum memory to use for multipart forms.

func WithShutdownTimeout

func WithShutdownTimeout(d time.Duration) Option

WithShutdownTimeout sets the timeout for graceful shutdown.

func WithStrictHeader

func WithStrictHeader() Option

WithStrictHeader enables strict mode for header parameters. If enabled, requests with unknown header parameters will return a 422 Unprocessable Entity.

func WithStrictQuery

func WithStrictQuery() Option

WithStrictQuery enables strict mode for query parameters. If enabled, requests with unknown query parameters will return a 422 Unprocessable Entity.

func WithValidator

func WithValidator(v Validator) Option

WithValidator sets a custom validator for the application.

type Route

type Route struct {
	Method      string
	Pattern     string
	Status      int
	Summary     string
	Description string
	OperationID string
	Deprecated  bool
	Internal    bool
	Tags        []string
	Security    []map[string][]string
	Schema      *bind.Schema
	OutputType  reflect.Type
	// contains filtered or unexported fields
}

Route represents a registered route and its metadata.

func (*Route) GetDeprecated

func (r *Route) GetDeprecated() bool

func (*Route) GetDescription

func (r *Route) GetDescription() string

func (*Route) GetInternal

func (r *Route) GetInternal() bool

func (*Route) GetMethod

func (r *Route) GetMethod() string

func (*Route) GetOperationID

func (r *Route) GetOperationID() string

func (*Route) GetOutputType

func (r *Route) GetOutputType() reflect.Type

func (*Route) GetPattern

func (r *Route) GetPattern() string

func (*Route) GetSchema

func (r *Route) GetSchema() *bind.Schema

func (*Route) GetSecurity

func (r *Route) GetSecurity() []map[string][]string

func (*Route) GetStatus

func (r *Route) GetStatus() int

func (*Route) GetSummary

func (r *Route) GetSummary() string

func (*Route) GetTags

func (r *Route) GetTags() []string

type RouteOption

type RouteOption func(*routeMeta)

RouteOption configures a specific route at registration time.

func WithDeprecated

func WithDeprecated() RouteOption

WithDeprecated marks the route as deprecated in OpenAPI.

func WithDescription

func WithDescription(s string) RouteOption

WithDescription sets the description for a route.

func WithInternal

func WithInternal() RouteOption

WithInternal marks the route as internal, hiding it from OpenAPI.

func WithMiddleware

func WithMiddleware(mw ...func(http.Handler) http.Handler) RouteOption

WithMiddleware adds route-local middleware.

func WithOperationID

func WithOperationID(id string) RouteOption

WithOperationID sets the OpenAPI operation ID for a route.

func WithSPA

func WithSPA() RouteOption

WithSPA enables single-page application mode for static file serving. If enabled, 404s will fallback to index.html at the root of the static directory.

func WithSecurity

func WithSecurity(security ...map[string][]string) RouteOption

WithSecurity adds OpenAPI security requirements to a route.

func WithSecurityName

func WithSecurityName(name string) RouteOption

WithSecurityName adds a simple security requirement by name with no scopes.

func WithStatus

func WithStatus(code int) RouteOption

WithStatus overrides the success HTTP status code for a route.

func WithSummary

func WithSummary(s string) RouteOption

WithSummary sets the summary for a route.

func WithTag

func WithTag(tag string) RouteOption

WithTag adds a single OpenAPI tag to a route.

func WithTags

func WithTags(tags ...string) RouteOption

WithTags adds OpenAPI tags to a route.

type Router

type Router interface {
	Handle(method, pattern string, handler http.Handler, route *Route)
	HandleHTTP(method, pattern string, handler http.Handler, opts ...RouteOption)
	Metrics(pattern string, handler http.Handler, opts ...RouteOption)
	App() *App
	Prefix() string
	Middleware() []func(http.Handler) http.Handler
	Static(prefix, root string, opts ...RouteOption)
	StaticFS(prefix string, fs http.FileSystem, opts ...RouteOption)
	WS(pattern string, handler any, opts ...RouteOption) error
}

Router is the interface implemented by App and Group for route registration.

type SSE

type SSE struct {
	Events <-chan Event
}

SSE represents a Server-Sent Events response.

type SecurityScheme

type SecurityScheme struct {
	Type             string
	Description      string
	Name             string // for apiKey
	In               string // for apiKey: "query", "header", "cookie"
	Scheme           string // for http
	BearerFormat     string // for http ("bearer")
	OpenIdConnectUrl string // for openIdConnect
}

SecurityScheme describes an authentication scheme for the API.

type Stream

type Stream struct {
	Reader      io.Reader
	ContentType string
}

Stream represents a streaming response.

type Validator

type Validator interface {
	Struct(s any) error
}

Validator is the interface that wraps the basic Validate method.

type Websocket

type Websocket[Msg any] struct {
	// contains filtered or unexported fields
}

Websocket is a typesafe wrapper around a websocket connection.

func (*Websocket[Msg]) Close

func (ws *Websocket[Msg]) Close(code websocket.StatusCode, reason string) error

Close closes the websocket connection with the given code and reason.

func (*Websocket[Msg]) Receive

func (ws *Websocket[Msg]) Receive(ctx context.Context) (Msg, error)

Receive receives a JSON message from the websocket connection.

func (*Websocket[Msg]) Send

func (ws *Websocket[Msg]) Send(ctx context.Context, msg Msg) error

Send sends a JSON message to the websocket connection.

type WebsocketHandler

type WebsocketHandler[In any, Msg any] func(ctx context.Context, in In, ws *Websocket[Msg]) error

WebsocketHandler is a typesafe websocket handler.

Directories

Path Synopsis
Package auth provides types and middleware for authenticated endpoints in Aku.
Package auth provides types and middleware for authenticated endpoints in Aku.
examples
basic command
security command
streaming command
internal

Jump to

Keyboard shortcuts

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