aero

package module
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2026 License: MIT Imports: 26 Imported by: 0

README

Aero

Blazing fast, zero-dependency, lightweight web framework for Go.

Features

  • Zero dependencies, pure stdlib, no transitive vulnerabilities
  • Zero allocations in the hot path
  • Faster than net/http 1.8x throughput, 60x less memory per request
  • Auto HTTP2 support
  • Hybrid routing with O(1) static map for exact paths, Segment Trie for dynamic ones
  • Order-sensitive middleware
  • WebSocket support

Guide

Installation
go get github.com/Alsond5/aero

Requires Go 1.25+

Using
package main

import (
	"fmt"
	"log/slog"
	"time"

	"github.com/Alsond5/aero"
)

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

	app.Use(Logger)

	app.GET("/api/users/:id", func(c *aero.Ctx) error {
		id := c.Param("id")
		return c.JSON(map[string]string{"id": id})
	})

	app.GET("/ws", aero.WebSocket(func(ws *aero.WSConn) {
		ws.Locals("client", "id")
		fmt.Println(ws.Locals("client"))

		for {
			mt, msg, err := ws.ReadMessage()
			if err != nil {
				fmt.Println(err)
				break
			}

			ws.WriteMessage(mt, msg)
		}
	}))

	app.Listen(":8080")
}

func Logger(c *aero.Ctx) error {
	start := time.Now()
	err := c.Next()
	duration := time.Since(start)

	slog.Info("request",
		"method", c.Method(),
		"path", c.Path(),
		"ip", c.IP(),
		"duration", duration,
		"status", c.ResponseStatus(),
	)

	return err
}

Benchmarks

Machine: Intel Core i7-10750H (unplugged, low-power mode) Go: 1.25 OS: Fedora Linux, amd64 Test: 1 middleware + 2 GET routes (1 dynamic, 1 static) + 1 POST route with JSON body parse

Standart
Framework ns/op B/op allocs/op req/s
Aero 603.8 339 3 1,656,177
Echo v5 772.7 336 4 1,294,163
net/http 727.9 333 4 1,373,815
Gin v1 955.2 368 5 1,046,901
Chi v5 1442.7 808 6 693,144
Routing
Framework ns/op B/op allocs/op req/s
Aero 194.8 0 0 5,133,470
Echo v5 232.6 16 1 4,299,226
net/http 242.2 20 1 4,128,819
Gin v1 277.6 52 2 3,602,305
Chi v5 1109.8 548 4 901,063
Parallel (12 goroutines)
Framework ns/op B/op allocs/op req/s
Aero 36.2 0 0 27,624,309
Echo v5 46.3 16 1 21,598,272
net/http 60.2 20 1 16,611,295
Gin v1 61.2 52 2 16,339,869
Chi v5 179.7 548 4 5,564,830
WebSocket (2000 concurrent connections)

Test: 2000 concurrent connections, 60s, 4 payload sizes (64B / 1KB / 4KB / 8KB), echo server

Framework msg/s p95 RTT p99 RTT max RTT Throughput
Aero 74,566 30ms 53ms 104ms 250 MB/s
Fiber v3 62,978 37ms 59ms 178ms 211 MB/s
WebSocket — Push Throughput (32 clients, 5s)

Test: Server pushes messages to 32 concurrent clients as fast as possible

Framework msg/s
Aero 5,772,032
Fiber v3 5,056,723

Design Decisions

Every feature is built on the Go standard library. No transitive vulnerabilities, no version conflicts, no go mod tidy surprises.

URL routing operates on path segments, not individual bytes. Radix Tree compression offers no benefit at segment granularity. A Segment Trie with a static map fast-path is simpler and equally fast.

Global middleware is stored once on the App. Routes store only an integer (middlewareCount). At dispatch time, the middleware slice and route handlers are indexed directly. No copying, no appending.

FastHTTP offers raw performance gains but breaks compatibility with the standard http.Handler ecosystem. Aero stays on net/http and achieves zero-alloc performance through careful design rather than a custom HTTP stack.

License

MIT License

Documentation

Index

Constants

View Source
const (
	MIMEApplicationJSON = "application/json"
	MIMEApplicationXML  = "application/xml"
	MIMETextXML         = "text/xml"
	MIMEApplicationForm = "application/x-www-form-urlencoded"
	MIMEMultipartForm   = "multipart/form-data"
)
View Source
const (
	RangeUnsatisfiable = -1
	RangeMalformed     = -2
)
View Source
const (
	HeaderTransferEncoding    = "Transfer-Encoding"
	HeaderContentType         = "Content-Type"
	HeaderContentLength       = "Content-Length"
	HeaderLink                = "Link"
	HeaderContentDisposition  = "Content-Disposition"
	HeaderXContentTypeOptions = "X-Content-Type-Options"
	HeaderReferer             = "Referer"
	HeaderLocation            = "Location"
	HeaderVary                = "Vary"
	HeaderCacheControl        = "Cache-Control"
)
View Source
const (
	MB int64 = 1 << 20
)
View Source
const (
	Version = "0.8.0"
)

Variables

View Source
var (
	ErrBindingTargetInvalid = errors.New("aero: binding target must be a pointer to a struct")
	ErrUnsupportedFieldType = errors.New("aero: unsupported field type")
)
View Source
var (
	ErrBodyAlreadyRead      = errors.New("aero: request body already read")
	ErrBodyTooLarge         = errors.New("aero: request body too large")
	ErrBodyEmpty            = errors.New("aero: request body is empty")
	ErrFormAlreadyParsed    = errors.New("aero: form already parsed")
	ErrNotMultipart         = errors.New("aero: content type is not multipart/form-data")
	ErrRangeNotPresent      = errors.New("aero: Range header not present")
	ErrRangeUnsatisfiable   = errors.New("aero: range not satisfiable")
	ErrRangeMalformed       = errors.New("aero: range header malformed")
	ErrUnsupportedMediaType = errors.New("aero: unsupported content encoding")
)
View Source
var (
	ErrFileNotFound    = errors.New("aero: file not found")
	ErrIsDirectory     = errors.New("aero: path is a directory")
	ErrPathRequired    = errors.New("aero: path is required")
	ErrPathNotAbsolute = errors.New("aero: path must be absolute or root must be specified")
)
View Source
var ErrTLSCertRequired = errors.New("aero: TLS cert and key are required")

Functions

This section is empty.

Types

type App

type App struct {
	NotFoundHandler         NotFoundHandler
	MethodNotAllowedHandler MethodNotAllowedHandler
	ErrorHandler            ErrorHandler
	OptionsHandler          OptionsHandler
	// contains filtered or unexported fields
}

func New

func New(config ...Config) *App

func (*App) DELETE

func (a *App) DELETE(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) GET

func (a *App) GET(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) Group added in v0.4.0

func (a *App) Group(prefix string, m ...HandlerFunc) (g *Group)

func (*App) HEAD

func (a *App) HEAD(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) Listen

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

func (*App) ListenTLS

func (a *App) ListenTLS(addr, cert, key string) error

func (*App) OPTIONS

func (a *App) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) PATCH

func (a *App) PATCH(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) POST

func (a *App) POST(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) PUT

func (a *App) PUT(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) ServeHTTP

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

func (*App) SetValidator added in v0.8.0

func (a *App) SetValidator(v Validator)

func (*App) TRACE added in v0.8.0

func (a *App) TRACE(path string, h HandlerFunc, m ...HandlerFunc)

func (*App) Use

func (a *App) Use(handlers ...HandlerFunc)

type Config

type Config struct {
	TrustProxy         bool
	SubdomainOffset    int
	MaxBodySize        int64
	MaxMultipartMemory int64
}

type CookieOptions

type CookieOptions struct {
	MaxAge   int
	Path     string
	Domain   string
	Secure   bool
	HttpOnly bool
	SameSite http.SameSite
}

type Ctx

type Ctx struct {
	Req
	Res
	// contains filtered or unexported fields
}

func (*Ctx) Next

func (c *Ctx) Next() error

type ErrorHandler added in v0.2.0

type ErrorHandler func(c *Ctx, err error)

type Group added in v0.4.0

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

func (*Group) DELETE added in v0.4.0

func (g *Group) DELETE(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) GET added in v0.4.0

func (g *Group) GET(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) Group added in v0.4.0

func (g *Group) Group(prefix string, m ...HandlerFunc) (group *Group)

func (*Group) HEAD added in v0.4.0

func (g *Group) HEAD(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) OPTIONS added in v0.4.0

func (g *Group) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) PATCH added in v0.4.0

func (g *Group) PATCH(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) POST added in v0.4.0

func (g *Group) POST(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) PUT added in v0.4.0

func (g *Group) PUT(path string, h HandlerFunc, m ...HandlerFunc)

func (*Group) Use added in v0.4.0

func (g *Group) Use(middleware ...HandlerFunc)

type HandlerFunc

type HandlerFunc func(c *Ctx) error

func WebSocket added in v0.6.0

func WebSocket(fn WebSocketHandler, config ...WSConfig) HandlerFunc

type MethodNotAllowedHandler added in v0.2.0

type MethodNotAllowedHandler func(allowed string, c *Ctx)

type NotFoundHandler added in v0.2.0

type NotFoundHandler func(c *Ctx)

type OptionsHandler added in v0.3.0

type OptionsHandler func(allowed string, c *Ctx)

type Param

type Param struct {
	Key   string
	Value string
}

type ParamValues

type ParamValues [maxParamCount]Param

type Range

type Range struct {
	Start int64
	End   int64
}

type RangeResult

type RangeResult struct {
	Type   string
	Ranges []Range
}

type Req

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

func (*Req) Accepts

func (req *Req) Accepts(types ...string) string

func (*Req) AcceptsCharsets

func (req *Req) AcceptsCharsets(charsets ...string) string

func (*Req) AcceptsEncodings

func (req *Req) AcceptsEncodings(encodings ...string) string

func (*Req) AcceptsLanguages

func (req *Req) AcceptsLanguages(langs ...string) string

func (*Req) AppendBody added in v0.8.0

func (r *Req) AppendBody(dst *[]byte) error

func (*Req) BaseURL

func (req *Req) BaseURL() string

func (*Req) Bind added in v0.8.0

func (req *Req) Bind(v any) error

func (*Req) BindForm added in v0.8.0

func (req *Req) BindForm(v any) error

func (*Req) BindHeaders added in v0.8.0

func (req *Req) BindHeaders(v any) error

func (*Req) BindJSON added in v0.8.0

func (req *Req) BindJSON(v any) error

func (*Req) BindParams added in v0.8.0

func (req *Req) BindParams(v any) error

func (*Req) BindQuery added in v0.8.0

func (req *Req) BindQuery(v any) error

func (*Req) BindXML added in v0.8.0

func (req *Req) BindXML(v any) error

func (*Req) Body

func (r *Req) Body() ([]byte, error)

func (*Req) BodyReader

func (r *Req) BodyReader() (io.ReadCloser, error)

func (*Req) Context

func (req *Req) Context() context.Context

func (*Req) Cookie

func (req *Req) Cookie(name string) (*http.Cookie, error)

func (*Req) Cookies

func (req *Req) Cookies() []*http.Cookie

func (*Req) FormFile

func (req *Req) FormFile(key string) (multipart.File, *multipart.FileHeader, error)

func (*Req) FormFiles

func (req *Req) FormFiles(key string) ([]*multipart.FileHeader, error)

func (*Req) FormValue

func (req *Req) FormValue(key string) string

func (*Req) FormValues

func (req *Req) FormValues() map[string][]string

func (*Req) Fresh

func (req *Req) Fresh() bool

func (*Req) Get

func (req *Req) Get(name string) string

func (*Req) Header

func (req *Req) Header(name string) string

func (*Req) Headers

func (req *Req) Headers() http.Header

func (*Req) Host

func (req *Req) Host() string

func (*Req) Hostname

func (req *Req) Hostname() string

func (*Req) IP

func (req *Req) IP() string

func (*Req) IPs

func (req *Req) IPs() []string

func (*Req) Method

func (req *Req) Method() string

func (*Req) MultipartReader

func (req *Req) MultipartReader() (*multipart.Reader, error)

func (*Req) OriginalURL

func (req *Req) OriginalURL() string

func (*Req) Param

func (req *Req) Param(key string) string

func (*Req) Params

func (req *Req) Params() []Param

func (*Req) Path

func (req *Req) Path() string

func (*Req) Protocol

func (req *Req) Protocol() string

func (*Req) Query

func (req *Req) Query(key string) string

func (*Req) QueryAll

func (req *Req) QueryAll() url.Values

func (*Req) Range

func (req *Req) Range(size int64, combine ...bool) (*RangeResult, error)

func (*Req) Secure

func (req *Req) Secure() bool

func (*Req) Stale

func (req *Req) Stale() bool

func (*Req) Subdomains

func (req *Req) Subdomains() []string

func (*Req) Validate added in v0.8.0

func (req *Req) Validate(i any) error

func (*Req) XHR

func (req *Req) XHR() bool

type Res

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

func (*Res) AddHeader

func (res *Res) AddHeader(key, value string) *Res

func (*Res) Attachment

func (res *Res) Attachment(filename ...string) *Res

func (*Res) ClearCookie

func (res *Res) ClearCookie(name string, opts ...CookieOptions) *Res

func (*Res) DeleteHeader

func (res *Res) DeleteHeader(key string) *Res

func (*Res) Download

func (res *Res) Download(path string, filename ...string) error

func (*Res) DownloadFS

func (res *Res) DownloadFS(fsys http.FileSystem, path string, filename ...string) error

func (*Res) Format

func (res *Res) Format(handlers map[string]func() error) error

func (*Res) GetHeader

func (res *Res) GetHeader(key string) string

func (*Res) JSON

func (res *Res) JSON(body any) error

func (*Res) JSONP

func (res *Res) JSONP(body any, callback string) error
func (res *Res) Links(links map[string]string) *Res

func (*Res) Location

func (res *Res) Location(url string) *Res

func (*Res) Redirect

func (res *Res) Redirect(url string, code ...int) error

func (*Res) ResponseStatus

func (res *Res) ResponseStatus() int

func (*Res) Send

func (res *Res) Send(body any) error

func (*Res) SendBytes

func (res *Res) SendBytes(body []byte) error

func (*Res) SendFile

func (res *Res) SendFile(path string, opts ...SendFileOptions) error

func (*Res) SendFileFS

func (res *Res) SendFileFS(fsys http.FileSystem, path string) error

func (*Res) SendStatus

func (res *Res) SendStatus(code int) error

func (*Res) SendString

func (res *Res) SendString(body string) error

func (*Res) SetCookie

func (res *Res) SetCookie(name, value string, opts ...CookieOptions) *Res

func (*Res) SetHeader

func (res *Res) SetHeader(key, value string) *Res

func (*Res) Status

func (res *Res) Status(code int) *Res

func (*Res) Type

func (res *Res) Type(t string) *Res

func (*Res) Vary

func (res *Res) Vary(field string) *Res

type Router

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

func NewRouter added in v0.2.0

func NewRouter() *Router

type SendFileOptions

type SendFileOptions struct {
	MaxAge  int
	Headers map[string]string
	Root    string
}

type ServerConfig

type ServerConfig struct {
	Addr            string
	Listener        net.Listener
	TLSCert         string
	TLSKey          string
	GracefulTimeout time.Duration
	OnShutdownError func(err error)
}

func (ServerConfig) Start

func (sc ServerConfig) Start(ctx context.Context, app *App) error

func (ServerConfig) StartTLS

func (sc ServerConfig) StartTLS(ctx context.Context, app *App) error

type Validator added in v0.8.0

type Validator interface {
	Validate(i any) error
}

type WSConfig added in v0.6.0

type WSConfig struct {
	Subprotocols     []string
	WriteTimeout     time.Duration
	Origins          []string
	AllowEmptyOrigin bool
	MaxMessageSize   uint64
}

type WSConn added in v0.6.0

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

func (*WSConn) Close added in v0.6.0

func (ws *WSConn) Close() error

func (*WSConn) CloseWithReason added in v0.6.0

func (ws *WSConn) CloseWithReason(code websocket.CloseStaatusCode, reason string) error

func (*WSConn) Locals added in v0.6.0

func (ws *WSConn) Locals(key string, value ...any) any

func (*WSConn) ReadMessage added in v0.6.0

func (ws *WSConn) ReadMessage() (int, []byte, error)

func (*WSConn) WriteMessage added in v0.6.0

func (ws *WSConn) WriteMessage(mt int, payload []byte) error

type WebSocketHandler added in v0.6.0

type WebSocketHandler func(*WSConn)

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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