Documentation
¶
Overview ¶
Package aero is a zero-dependency, high-performance HTTP web framework for Go. It is designed for minimal allocations on the hot path, making it suitable for latency-sensitive applications.
Overview ¶
Aero provides a fast trie-based router with support for named URL parameters, route groups, and a hybrid middleware chain model that allows both global and group/route-level middlewares. The framework is built entirely on top of the Go standard library with no external dependencies.
Key characteristics:
- Zero external dependencies
- Trie-based router with zero allocations on matched routes
- Hybrid middleware chain: global (App.Use) and scoped (Group.Use)
- First-class WebSocket support via a custom RFC 6455 implementation
- Built-in request binding, content negotiation, and SSE support
- Graceful shutdown via ServerConfig
Getting Started ¶
Create an application with New, register routes, and start the server:
app := aero.New()
app.GET("/", func(c *aero.Ctx) error {
return c.Res.SendString("Hello, World!")
})
app.Listen(":8080")
Route Groups ¶
Routes can be grouped under a common prefix with shared middlewares:
api := app.Group("/api", authMiddleware)
api.GET("/users", listUsers) // GET /api/users
api.POST("/users", createUser) // POST /api/users
Middleware ¶
Middlewares are regular HandlerFunc functions that call Ctx.Next to pass control to the next handler in the chain:
app.Use(func(c *aero.Ctx) error {
start := time.Now()
err := c.Next()
log.Printf("%s %s — %v", c.Req.Method(), c.Req.Path(), time.Since(start))
return err
})
WebSocket ¶
WebSocket endpoints are registered as regular routes using WebSocket:
app.GET("/ws", aero.WebSocket(func(ws *aero.WSConn) {
for {
mt, msg, err := ws.ReadMessage()
if err != nil {
return
}
ws.WriteMessage(mt, msg)
}
}))
Request Binding ¶
Incoming request data can be bound directly into structs. Each field's struct tag determines the source (json, form, query, param, header):
type CreateUserReq struct {
OrgID string `param:"orgId"`
Token string `header:"X-Auth-Token"`
Name string `json:"name"`
}
var req CreateUserReq
if err := c.Req.Bind(&req); err != nil {
return err
}
Graceful Shutdown ¶
For production use, ServerConfig provides context-aware lifecycle control:
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
sc := aero.ServerConfig{
Addr: ":8080",
GracefulTimeout: 10 * time.Second,
}
if err := sc.Start(ctx, app); err != nil {
log.Fatal(err)
}
Index ¶
- Constants
- Variables
- type App
- func (a *App) DELETE(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) GET(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) Group(prefix string, m ...HandlerFunc) (g *Group)
- func (a *App) HEAD(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) Listen(addr string) error
- func (a *App) ListenTLS(addr, cert, key string) error
- func (a *App) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) PATCH(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) POST(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) PUT(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (a *App) SetValidator(v Validator)
- func (a *App) TRACE(path string, h HandlerFunc, m ...HandlerFunc)
- func (a *App) Use(handlers ...HandlerFunc)
- type Config
- type CookieOptions
- type Ctx
- type ErrorHandler
- type Group
- func (g *Group) DELETE(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) GET(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) Group(prefix string, m ...HandlerFunc) (group *Group)
- func (g *Group) HEAD(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) PATCH(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) POST(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) PUT(path string, h HandlerFunc, m ...HandlerFunc)
- func (g *Group) Use(middleware ...HandlerFunc)
- type HandlerFunc
- type MethodNotAllowedHandler
- type NotFoundHandler
- type OptionsHandler
- type Param
- type ParamValues
- type Range
- type RangeResult
- type Req
- func (req *Req) Accepts(types ...string) string
- func (req *Req) AcceptsCharsets(charsets ...string) string
- func (req *Req) AcceptsEncodings(encodings ...string) string
- func (req *Req) AcceptsLanguages(langs ...string) string
- func (r *Req) AppendBody(dst *[]byte) error
- func (req *Req) BaseURL() string
- func (req *Req) Bind(v any) error
- func (req *Req) BindForm(v any) error
- func (req *Req) BindHeaders(v any) error
- func (req *Req) BindJSON(v any) error
- func (req *Req) BindParams(v any) error
- func (req *Req) BindQuery(v any) error
- func (req *Req) BindXML(v any) error
- func (r *Req) Body() ([]byte, error)
- func (r *Req) BodyReader() (io.ReadCloser, error)
- func (req *Req) Context() context.Context
- func (req *Req) Cookie(name string) (*http.Cookie, error)
- func (req *Req) Cookies() []*http.Cookie
- func (req *Req) FormFile(key string) (multipart.File, *multipart.FileHeader, error)
- func (req *Req) FormFiles(key string) ([]*multipart.FileHeader, error)
- func (req *Req) FormValue(key string) string
- func (req *Req) FormValues() map[string][]string
- func (req *Req) Fresh() bool
- func (req *Req) Get(name string) string
- func (req *Req) Header(name string) string
- func (req *Req) Headers() http.Header
- func (req *Req) Host() string
- func (req *Req) Hostname() string
- func (req *Req) IP() string
- func (req *Req) IPs() []string
- func (req *Req) Method() string
- func (req *Req) MultipartReader() (*multipart.Reader, error)
- func (req *Req) OriginalURL() string
- func (req *Req) Param(key string) string
- func (req *Req) Params() []Param
- func (req *Req) Path() string
- func (req *Req) Protocol() string
- func (req *Req) Query(key string) string
- func (req *Req) QueryAll() url.Values
- func (req *Req) Range(size int64, combine ...bool) (*RangeResult, error)
- func (req *Req) Secure() bool
- func (req *Req) Stale() bool
- func (req *Req) Subdomains() []string
- func (req *Req) Validate(i any) error
- func (req *Req) XHR() bool
- type Res
- func (res *Res) AddHeader(key, value string) *Res
- func (res *Res) Attachment(filename ...string) *Res
- func (res *Res) ClearCookie(name string, opts ...CookieOptions) *Res
- func (res *Res) DeleteHeader(key string) *Res
- func (res *Res) Download(path string, filename ...string) error
- func (res *Res) DownloadFS(fsys http.FileSystem, path string, filename ...string) error
- func (res *Res) Format(handlers map[string]func() error) error
- func (res *Res) GetHeader(key string) string
- func (res *Res) JSON(body any) error
- func (res *Res) JSONP(body any, callback string) error
- func (res *Res) Links(links map[string]string) *Res
- func (res *Res) Location(url string) *Res
- func (res *Res) Redirect(url string, code ...int) error
- func (res *Res) ResponseStatus() int
- func (res *Res) Send(body any) error
- func (res *Res) SendBytes(body []byte) error
- func (res *Res) SendFile(path string, opts ...SendFileOptions) error
- func (res *Res) SendFileFS(fsys http.FileSystem, path string) error
- func (res *Res) SendStatus(code int) error
- func (res *Res) SendString(body string) error
- func (res *Res) SetCookie(name, value string, opts ...CookieOptions) *Res
- func (res *Res) SetHeader(key, value string) *Res
- func (res *Res) Status(code int) *Res
- func (res *Res) Type(t string) *Res
- func (res *Res) Vary(field string) *Res
- type SSEWriter
- type SendFileOptions
- type ServerConfig
- type Validator
- type WSConfig
- type WSConn
- type WebSocketHandler
Constants ¶
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" HeaderConnection = "Connection" )
const ( MIMEApplicationJSON = "application/json" MIMEApplicationXML = "application/xml" MIMETextXML = "text/xml" MIMEApplicationForm = "application/x-www-form-urlencoded" MIMEMultipartForm = "multipart/form-data" )
const ( RangeUnsatisfiable = -1 RangeMalformed = -2 )
const (
MB int64 = 1 << 20
)
MB is a convenience constant representing one megabyte (1 << 20 bytes). Used as a base unit for body size limits in Config.
const (
Version = "0.8.6"
)
Variables ¶
var ( ErrBindingTargetInvalid = errors.New("aero: binding target must be a pointer to a struct") ErrUnsupportedFieldType = errors.New("aero: unsupported field type") )
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") )
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") )
var ErrTLSCertRequired = errors.New("aero: TLS cert and key are required")
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// NotFoundHandler is called when no route matches the request path.
// Defaults to a 404 JSON response if not set.
NotFoundHandler NotFoundHandler
// MethodNotAllowedHandler is called when a route exists for the
// requested path but not for the requested HTTP method.
// Defaults to a 405 response with an Allow header if not set.
MethodNotAllowedHandler MethodNotAllowedHandler
// ErrorHandler is called whenever a HandlerFunc returns a non-nil error.
// Defaults to a 500 JSON response if not set.
ErrorHandler ErrorHandler
// OptionsHandler is called for OPTIONS requests that do not have
// an explicitly registered OPTIONS route.
// Defaults to a 204 response with an Allow header if not set.
OptionsHandler OptionsHandler
// contains filtered or unexported fields
}
App is the core Aero application instance. It holds the router, middleware chain, configuration, and lifecycle hooks. Create a new instance with New.
App implements http.Handler, so it can be passed directly to any standard Go HTTP server.
func New ¶
New creates and returns a new Aero application instance. An optional Config can be provided to override defaults.
app := aero.New()
app := aero.New(aero.Config{ ... })
func (*App) DELETE ¶
func (a *App) DELETE(path string, h HandlerFunc, m ...HandlerFunc)
DELETE registers a route for HTTP DELETE requests on the given path.
func (*App) GET ¶
func (a *App) GET(path string, h HandlerFunc, m ...HandlerFunc)
GET registers a route for HTTP GET requests on the given path. Route-level middlewares can be appended after the handler.
app.GET("/users", listUsers)
app.GET("/users/:id", getUser, authMiddleware)
func (*App) Group ¶ added in v0.4.0
func (a *App) Group(prefix string, m ...HandlerFunc) (g *Group)
Group creates a new route group with the given path prefix and optional group-level middlewares. Routes registered on the group inherit the prefix and its middlewares.
api := app.Group("/api", authMiddleware)
api.GET("/users", listUsers) // → GET /api/users
func (*App) HEAD ¶
func (a *App) HEAD(path string, h HandlerFunc, m ...HandlerFunc)
HEAD registers a route for HTTP HEAD requests on the given path.
func (*App) Listen ¶
Listen starts the HTTP server on the given address. The address format follows standard Go net/http conventions (e.g. ":8080").
app.Listen(":8080")
func (*App) ListenTLS ¶
ListenTLS starts an HTTPS server on the given address using the provided TLS certificate and key files.
app.ListenTLS(":443", "cert.pem", "key.pem")
func (*App) OPTIONS ¶
func (a *App) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)
OPTIONS registers a route for HTTP OPTIONS requests on the given path.
func (*App) PATCH ¶
func (a *App) PATCH(path string, h HandlerFunc, m ...HandlerFunc)
PATCH registers a route for HTTP PATCH requests on the given path.
func (*App) POST ¶
func (a *App) POST(path string, h HandlerFunc, m ...HandlerFunc)
POST registers a route for HTTP POST requests on the given path.
func (*App) PUT ¶
func (a *App) PUT(path string, h HandlerFunc, m ...HandlerFunc)
PUT registers a route for HTTP PUT requests on the given path.
func (*App) ServeHTTP ¶
func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler, enabling Aero to be used with any standard Go HTTP server or middleware.
func (*App) SetValidator ¶ added in v0.8.0
SetValidator sets the validator used by Req.Validate. The validator must implement the Validator interface.
func (*App) TRACE ¶ added in v0.7.1
func (a *App) TRACE(path string, h HandlerFunc, m ...HandlerFunc)
TRACE registers a route for HTTP TRACE requests on the given path.
func (*App) Use ¶
func (a *App) Use(handlers ...HandlerFunc)
Use registers one or more global middlewares that run on every request, regardless of the route. Middlewares are executed in the order they are added.
app.Use(logger, recover, cors)
type Config ¶
type Config struct {
// TrustProxy enables parsing of proxy-forwarded headers such as
// X-Forwarded-For and X-Forwarded-Proto when determining the
// client IP and protocol. Enable only if Aero sits behind a
// trusted reverse proxy. Default: false.
TrustProxy bool
// SubdomainOffset controls how many dot-separated segments are
// stripped from the right of the hostname when extracting subdomains
// via [Req.Subdomains]. For example, an offset of 2 on "a.b.example.com"
// yields ["a", "b"]. Default: 2.
SubdomainOffset int
// MaxBodySize is the maximum allowed size in bytes for a request body.
// Requests exceeding this limit are rejected before the body is read.
// Default: 4 MB.
MaxBodySize int64
// MaxMultipartMemory is the maximum amount of memory in bytes used
// when parsing multipart/form-data requests. Parts exceeding this
// limit are stored in temporary files. Default: 32 MB.
MaxMultipartMemory int64
}
Config holds application-level configuration options. All fields are optional; unset fields fall back to the defaults defined in [defaultConfig].
app := aero.New(aero.Config{
TrustProxy: true,
MaxBodySize: 8 * aero.MB,
})
type CookieOptions ¶
type CookieOptions struct {
// MaxAge sets the cookie's Max-Age attribute in seconds.
// A negative value instructs the client to delete the cookie immediately.
MaxAge int
// Path restricts the cookie to the given URL path prefix.
// Defaults to "/" if empty.
Path string
// Domain sets the cookie's Domain attribute, controlling which hosts
// receive the cookie. Omit to default to the current host only.
Domain string
// Secure marks the cookie to be sent only over HTTPS connections.
Secure bool
// HttpOnly prevents the cookie from being accessed via JavaScript,
// mitigating XSS exposure.
HttpOnly bool
// SameSite controls cross-site request behaviour for the cookie.
// Accepts [http.SameSiteStrictMode], [http.SameSiteLaxMode], or
// [http.SameSiteNoneMode].
SameSite http.SameSite
}
CookieOptions configures the attributes of a cookie set via Res.SetCookie or cleared via Res.ClearCookie.
type Ctx ¶
type Ctx struct {
// Req provides access to all incoming request data: headers, params,
// query string, body, cookies, and more.
Req
// Res provides methods for building and sending the HTTP response:
// status codes, headers, JSON, files, redirects, and more.
Res
// contains filtered or unexported fields
}
Ctx is the request context passed to every HandlerFunc. It embeds Req and Res directly, so request reading and response writing methods are accessible without any extra field access.
app.GET("/hello", func(c *aero.Ctx) error {
name := c.Req.Param("name")
return c.Res.SendString("Hello, " + name)
})
func (*Ctx) Next ¶
Next executes the next handler or middleware in the chain for the current route. It must be called inside a middleware to pass control forward. Calling Next after the chain is exhausted is a no-op and returns nil.
func logger(c *aero.Ctx) error {
start := time.Now()
err := c.Next()
log.Printf("%s %s — %v", c.Req.Method(), c.Req.Path(), time.Since(start))
return err
}
func (*Ctx) SSE ¶ added in v0.8.1
SSE upgrades the current request to a Server-Sent Events stream and returns an SSEWriter for pushing events to the client. The second return value reports whether the upgrade succeeded; it is false if the underlying ResponseWriter does not support flushing (i.e. does not implement http.Flusher).
The response Content-Type is automatically set to "text/event-stream" and caching is disabled. The connection is kept open until the handler returns.
app.GET("/events", func(c *aero.Ctx) error {
sse, ok := c.SSE()
if !ok {
return c.Res.SendStatus(http.StatusInternalServerError)
}
sse.Send("hello")
return nil
})
type ErrorHandler ¶ added in v0.2.0
type Group ¶ added in v0.4.0
type Group struct {
// contains filtered or unexported fields
}
Group represents a set of routes sharing a common path prefix and an optional set of group-level middlewares. Create a group via App.Group or Group.Group.
func (*Group) DELETE ¶ added in v0.4.0
func (g *Group) DELETE(path string, h HandlerFunc, m ...HandlerFunc)
DELETE registers a DELETE route under this group's prefix.
func (*Group) GET ¶ added in v0.4.0
func (g *Group) GET(path string, h HandlerFunc, m ...HandlerFunc)
GET registers a GET route under this group's prefix.
v1 := app.Group("/v1")
v1.GET("/ping", pingHandler) // → GET /v1/ping
func (*Group) Group ¶ added in v0.4.0
func (g *Group) Group(prefix string, m ...HandlerFunc) (group *Group)
Group creates a nested sub-group under the current group's prefix. The sub-group inherits the parent's middlewares and prepends its own prefix.
api := app.Group("/api")
v2 := api.Group("/v2", versionMiddleware) // → prefix: /api/v2
func (*Group) HEAD ¶ added in v0.4.0
func (g *Group) HEAD(path string, h HandlerFunc, m ...HandlerFunc)
HEAD registers a HEAD route under this group's prefix.
func (*Group) OPTIONS ¶ added in v0.4.0
func (g *Group) OPTIONS(path string, h HandlerFunc, m ...HandlerFunc)
OPTIONS registers an OPTIONS route under this group's prefix.
func (*Group) PATCH ¶ added in v0.4.0
func (g *Group) PATCH(path string, h HandlerFunc, m ...HandlerFunc)
PATCH registers a PATCH route under this group's prefix.
func (*Group) POST ¶ added in v0.4.0
func (g *Group) POST(path string, h HandlerFunc, m ...HandlerFunc)
POST registers a POST route under this group's prefix.
func (*Group) PUT ¶ added in v0.4.0
func (g *Group) PUT(path string, h HandlerFunc, m ...HandlerFunc)
PUT registers a PUT route under this group's prefix.
func (*Group) Use ¶ added in v0.4.0
func (g *Group) Use(middleware ...HandlerFunc)
Use registers one or more middlewares scoped to this group. These middlewares run after global middlewares and before the route handler.
admin := app.Group("/admin")
admin.Use(adminAuthMiddleware)
type HandlerFunc ¶
HandlerFunc is the core handler type in Aero. Every route handler and middleware must match this signature. Returning a non-nil error passes it to the application's ErrorHandler.
app.GET("/hello", func(c *aero.Ctx) error {
return c.Res.SendString("Hello, World!")
})
func WebSocket ¶ added in v0.6.0
func WebSocket(fn WebSocketHandler, config ...WSConfig) HandlerFunc
WebSocket returns a HandlerFunc that upgrades the HTTP connection to WebSocket and calls fn with the established WSConn. The connection is closed automatically when fn returns. An optional WSConfig can be provided to configure subprotocols, origin policy, and message limits.
app.GET("/ws", aero.WebSocket(func(ws *aero.WSConn) {
mt, msg, err := ws.ReadMessage()
if err != nil {
return
}
ws.WriteMessage(mt, msg)
}))
type MethodNotAllowedHandler ¶ added in v0.2.0
type NotFoundHandler ¶ added in v0.2.0
type NotFoundHandler func(c *Ctx)
type OptionsHandler ¶ added in v0.3.0
type ParamValues ¶
type ParamValues [maxParamCount]Param
type RangeResult ¶
type Req ¶
type Req struct {
// contains filtered or unexported fields
}
Req provides access to all incoming HTTP request data. It is embedded in Ctx and should not be instantiated directly.
func (*Req) Accepts ¶
Accepts checks the request's Accept header against the provided MIME types and returns the best match, respecting quality values (q-factors). Returns an empty string if none of the types are acceptable.
best := c.Req.Accepts("text/html", "application/json")
func (*Req) AcceptsCharsets ¶
AcceptsCharsets checks the Accept-Charset header against the provided charsets and returns the best match. Returns an empty string if none match.
func (*Req) AcceptsEncodings ¶
AcceptsEncodings checks the Accept-Encoding header against the provided encodings and returns the best match. Returns an empty string if none match.
enc := c.Req.AcceptsEncodings("gzip", "deflate", "identity")
func (*Req) AcceptsLanguages ¶
AcceptsLanguages checks the Accept-Language header against the provided language tags and returns the best match. Returns an empty string if none match.
lang := c.Req.AcceptsLanguages("en", "tr", "de")
func (*Req) AppendBody ¶ added in v0.8.0
AppendBody reads the full request body into dst, growing the slice as needed. It transparently decompresses gzip and deflate encoded bodies. The body can only be read once; subsequent calls return ErrBodyAlreadyRead. MaxBodySize from Config is enforced; exceeding it returns ErrBodyTooLarge.
Prefer this over Req.Body when you already have a buffer to reuse.
func (*Req) BaseURL ¶
BaseURL returns the base URL of the request, consisting of the protocol and host only (e.g. "https://example.com").
func (*Req) Bind ¶ added in v0.8.0
Bind parses the request into v by reading each struct field's tag to determine the source. Supported tags are "json", "xml", "form", "query", "param", and "header". A single struct can mix multiple sources; Bind fills each field from the appropriate location.
type CreateUserReq struct {
OrgID string `param:"orgId"`
Token string `header:"X-Auth-Token"`
Page int `query:"page"`
Name string `json:"name"`
}
var req CreateUserReq
if err := c.Req.Bind(&req); err != nil {
return err
}
func (*Req) BindForm ¶ added in v0.8.0
BindForm parses the request body as application/x-www-form-urlencoded or multipart/form-data and maps the values into v using the "form" struct tag.
func (*Req) BindHeaders ¶ added in v0.8.0
BindHeaders maps request headers into v using the "header" struct tag. Header names are case-insensitive.
type AuthReq struct {
Token string `header:"X-Auth-Token"`
}
func (*Req) BindJSON ¶ added in v0.8.0
BindJSON decodes the request body as JSON into v. Returns an error if the Content-Type is not application/json or if decoding fails.
func (*Req) BindParams ¶ added in v0.8.0
BindParams maps URL path parameters into v using the "param" struct tag.
type UserReq struct {
ID string `param:"id"`
}
func (*Req) BindQuery ¶ added in v0.8.0
BindQuery maps URL query parameters into v using the "query" struct tag.
type SearchReq struct {
Q string `query:"q"`
Page int `query:"page"`
}
func (*Req) BindXML ¶ added in v0.8.0
BindXML decodes the request body as XML into v. Returns an error if the Content-Type is not application/xml or if decoding fails.
func (*Req) Body ¶
Body reads and returns the full request body as a byte slice. It transparently decompresses gzip and deflate encoded bodies. The body can only be read once; subsequent calls return ErrBodyAlreadyRead. MaxBodySize from Config is enforced; exceeding it returns ErrBodyTooLarge.
Use Req.AppendBody to read into an existing buffer, or Req.BodyReader to stream the body without buffering.
func (*Req) BodyReader ¶
func (r *Req) BodyReader() (io.ReadCloser, error)
BodyReader returns the raw request body as an io.ReadCloser for streaming reads without buffering the entire body into memory. The caller is responsible for closing the reader. The body can only be read once; subsequent calls return ErrBodyAlreadyRead.
Note: Content-Encoding decompression is not applied. Use Req.Body or Req.AppendBody if transparent decompression is needed.
func (*Req) Context ¶
Context returns the standard context.Context associated with the current request, as provided by the underlying http.Request.
func (*Req) Cookie ¶
Cookie returns the named cookie from the request. Returns http.ErrNoCookie if the cookie is not present.
func (*Req) FormFile ¶
FormFile returns the first uploaded file associated with the given form field name. The caller is responsible for closing the returned multipart.File.
func (*Req) FormFiles ¶
func (req *Req) FormFiles(key string) ([]*multipart.FileHeader, error)
FormFiles returns all uploaded files for the given form field name. Useful when a single field accepts multiple file uploads.
func (*Req) FormValue ¶
FormValue returns the value of the named field from a parsed application/x-www-form-urlencoded or multipart/form-data body. Returns an empty string if the field is not present.
func (*Req) FormValues ¶
FormValues returns all form fields as a map of key to value slices, supporting both application/x-www-form-urlencoded and multipart/form-data.
func (*Req) Fresh ¶
Fresh reports whether the request is considered fresh by comparing the ETag and Last-Modified response headers against the corresponding If-None-Match and If-Modified-Since request headers. Typically used to implement conditional GET responses.
func (*Req) Get ¶
Get returns the value of the named request header. The name is case-insensitive. Returns an empty string if not present.
func (*Req) Header ¶
Header returns the value of the named request header. The name is case-insensitive. Returns an empty string if not present. Alias of Req.Get.
func (*Req) Headers ¶
Headers returns all request headers as an http.Header map.
func (*Req) Host ¶
Host returns the host portion of the request, including the port if present (e.g. "example.com:8080"). It reads from the Host header or the URL.
func (*Req) Hostname ¶
Hostname returns the host portion of the request without the port (e.g. "example.com").
func (*Req) IP ¶
IP returns the originating IP address of the request. When [Config.TrustProxy] is enabled, the leftmost address in the X-Forwarded-For header is returned.
func (*Req) IPs ¶
IPs returns all IP addresses in the X-Forwarded-For header, in order from client to the nearest proxy. Returns a nil slice if the header is absent or [Config.TrustProxy] is disabled.
func (*Req) MultipartReader ¶
MultipartReader returns a multipart.Reader for streaming a multipart/form-data body part by part, without buffering it into memory. Returns an error if the request is not multipart.
func (*Req) OriginalURL ¶
OriginalURL returns the full request URL as received, including path and raw query string.
func (*Req) Param ¶
Param returns the value of the named URL path parameter. Returns an empty string if the parameter is not defined on the route.
// Route: /users/:id
id := c.Req.Param("id")
func (*Req) Params ¶
Params returns all URL path parameters for the current route as a slice of Param key-value pairs.
func (*Req) Protocol ¶
Protocol returns the request protocol string, either "http" or "https". When [Config.TrustProxy] is enabled, the X-Forwarded-Proto header is consulted first.
func (*Req) Query ¶
Query returns the value of the named URL query parameter. Returns an empty string if the key is not present.
// GET /search?q=aero
q := c.Req.Query("q")
func (*Req) QueryAll ¶
QueryAll returns all URL query parameters as url.Values.
func (*Req) Range ¶
func (req *Req) Range(size int64, combine ...bool) (*RangeResult, error)
Range parses the Range header for a resource of the given size in bytes and returns the requested byte ranges. If combine is true, overlapping or adjacent ranges are merged into a single range. Returns an error if the header is malformed or ranges are unsatisfiable.
func (*Req) Secure ¶
Secure reports whether the request was made over HTTPS. Equivalent to checking Protocol() == "https".
func (*Req) Stale ¶
Stale reports whether the request is considered stale. It is the inverse of Req.Fresh.
func (*Req) Subdomains ¶
Subdomains returns the subdomains of the request hostname as a slice, ordered from most specific to least specific. The number of segments trimmed from the right is controlled by [Config.SubdomainOffset].
// Host: api.v2.example.com, SubdomainOffset: 2 // → ["api", "v2"]
func (*Req) Validate ¶ added in v0.8.0
Validate runs the application's configured Validator against i. Returns an error if validation fails or if no validator has been set via App.SetValidator.
type Res ¶
type Res struct {
// contains filtered or unexported fields
}
Res provides methods for building and sending the HTTP response. It is embedded in Ctx and should not be instantiated directly.
func (*Res) AddHeader ¶
AddHeader appends a value to a response header without replacing existing values. Returns *Res for chaining.
func (*Res) Attachment ¶
Attachment sets the Content-Disposition header to "attachment", prompting the browser to download the response rather than display it. An optional filename is included in the header when provided.
c.Res.Attachment("report.pdf")
func (*Res) ClearCookie ¶
func (res *Res) ClearCookie(name string, opts ...CookieOptions) *Res
ClearCookie expires the named cookie on the client by setting its Max-Age to -1. Optional CookieOptions can be provided to match the original cookie's path and domain. Returns *Res for chaining.
func (*Res) DeleteHeader ¶
DeleteHeader removes the named header from the response. Returns *Res for chaining.
func (*Res) Download ¶
Download serves a file as a downloadable attachment. It behaves like Res.SendFile but also sets Content-Disposition to "attachment". An optional filename overrides the name shown in the browser's save dialog.
func (*Res) DownloadFS ¶
DownloadFS serves a file from the provided http.FileSystem as a downloadable attachment. See Res.Download and Res.SendFileFS.
func (*Res) Format ¶
Format performs content negotiation using the request's Accept header. handlers is a map of MIME type to handler function; the best matching handler is called. Returns an error if no match is found.
c.Res.Format(map[string]func(...){
"application/json": func(...) { c.Res.JSON(data) },
"text/html": func(...) { c.Res.SendString("<p>data</p>") },
})
func (*Res) GetHeader ¶
GetHeader returns the current value of the named response header. Returns an empty string if the header has not been set.
func (*Res) JSON ¶
JSON serializes body to JSON and writes it with Content-Type application/json. Returns an error if serialization fails.
c.Res.JSON(map[string]any{"ok": true})
func (*Res) JSONP ¶
JSONP sends a JSONP response by wrapping the JSON-serialized body in the provided JavaScript callback. The callback name is validated against a safe identifier allowlist to prevent XSS.
c.Res.JSONP(data, "cb")
// → cb({"key":"value"});
func (*Res) Links ¶
Links sets the Link response header from the provided map of relation to URL. Multiple relations are comma-separated per RFC 8288.
c.Res.Links(map[string]string{
"next": "/page/3",
"prev": "/page/1",
})
func (*Res) Location ¶
Location sets the Location response header to the given URL. Returns *Res for chaining.
func (*Res) Redirect ¶
Redirect sends an HTTP redirect to the given URL. The status code defaults to 302 (Found) if not provided; any 3xx code is accepted.
c.Res.Redirect("/login")
c.Res.Redirect("/new-path", http.StatusMovedPermanently)
func (*Res) ResponseStatus ¶
ResponseStatus returns the HTTP status code that will be (or has been) written for this response. Defaults to 200 if Res.Status was not called.
func (*Res) Send ¶
Send writes body to the response. The Content-Type is inferred from the value type: []byte and string are sent as-is, all other types are JSON-encoded. For 204, 304 responses the body is automatically discarded and content-related headers are stripped. HEAD requests are handled correctly.
c.Res.Send("hello")
c.Res.Send(myStruct)
func (*Res) SendBytes ¶
SendBytes writes a raw byte slice body. Content-Type defaults to application/octet-stream unless set beforehand.
func (*Res) SendFile ¶
func (res *Res) SendFile(path string, opts ...SendFileOptions) error
SendFile serves a file from the local filesystem at the given path. It sets Content-Type based on the file extension, supports Range requests, and accepts optional SendFileOptions (e.g. root directory restriction). Path traversal outside the configured root is rejected.
func (*Res) SendFileFS ¶
func (res *Res) SendFileFS(fsys http.FileSystem, path string) error
SendFileFS serves a file from the provided http.FileSystem at the given path. Useful for serving embedded files (e.g. via go:embed).
func (*Res) SendStatus ¶
SendStatus writes the given HTTP status code and immediately flushes the response with no body. Useful for sending header-only responses such as 204 No Content or 401 Unauthorized.
return c.Res.SendStatus(http.StatusNoContent)
func (*Res) SendString ¶
SendString writes a plain string body with Content-Type text/plain.
func (*Res) SetCookie ¶
func (res *Res) SetCookie(name, value string, opts ...CookieOptions) *Res
SetCookie adds a Set-Cookie header to the response with the given name, value, and optional CookieOptions (path, domain, expiry, flags, etc.). Returns *Res for chaining.
func (*Res) SetHeader ¶
SetHeader sets a response header, replacing any existing value. Returns *Res for chaining.
func (*Res) Status ¶
Status sets the HTTP status code for the response. Returns *Res to allow method chaining before a final send call.
c.Res.Status(http.StatusCreated).JSON(body)
type SSEWriter ¶ added in v0.8.1
type SSEWriter struct {
// contains filtered or unexported fields
}
SSEWriter writes Server-Sent Events to the client over an open HTTP connection. Obtain an instance via Ctx.SSE.
func (*SSEWriter) Send ¶ added in v0.8.1
Send writes a data-only SSE event to the client and flushes immediately.
sse.Send("ping")
// event stream: "data: ping\n\n"
func (*SSEWriter) SendEvent ¶ added in v0.8.1
SendEvent writes a named SSE event with data to the client and flushes.
sse.SendEvent("update", `{"count":42}`)
// event stream: "event: update\ndata: {\"count\":42}\n\n"
func (*SSEWriter) SendID ¶ added in v0.8.1
SendID writes a data event with an explicit event ID to the client and flushes. The ID allows clients to resume the stream from the last seen event via the Last-Event-ID header on reconnect.
sse.SendID("msg-42", "hello again")
// event stream: "id: msg-42\ndata: hello again\n\n"
type SendFileOptions ¶
type SendFileOptions struct {
// MaxAge sets the Cache-Control max-age directive in seconds for the
// served file. A value of 0 disables caching headers.
MaxAge int
// Headers is a map of additional response headers to set when serving
// the file (e.g. custom Cache-Control directives, CORS headers).
Headers map[string]string
// Root restricts file serving to the given directory. Any path that
// resolves outside Root is rejected to prevent directory traversal attacks.
// If empty, no restriction is applied.
Root string
}
SendFileOptions configures the behaviour of Res.SendFile and Res.Download.
type ServerConfig ¶
type ServerConfig struct {
// Addr is the TCP address to listen on (e.g. ":8080", "0.0.0.0:443").
// Ignored if Listener is provided.
Addr string
// Listener is an optional pre-configured [net.Listener]. When set,
// Addr is ignored and the server accepts connections from this listener.
// Useful for testing or socket activation scenarios.
Listener net.Listener
// TLSCert is the path to the TLS certificate file (PEM encoded).
// Required for [ServerConfig.StartTLS].
TLSCert string
// TLSKey is the path to the TLS private key file (PEM encoded).
// Required for [ServerConfig.StartTLS].
TLSKey string
// GracefulTimeout is the maximum duration to wait for in-flight requests
// to complete during shutdown. If zero, the server waits indefinitely
// until ctx is cancelled.
GracefulTimeout time.Duration
// OnShutdownError is an optional callback invoked if the graceful shutdown
// itself returns an error (e.g. timeout exceeded). If nil, shutdown errors
// are silently discarded.
OnShutdownError func(err error)
}
ServerConfig holds the configuration for starting an Aero server with context-aware lifecycle management and graceful shutdown. Use ServerConfig.Start or ServerConfig.StartTLS instead of App.Listen when you need shutdown control via context.Context.
sc := aero.ServerConfig{Addr: ":8080"}
if err := sc.Start(ctx, app); err != nil {
log.Fatal(err)
}
func (ServerConfig) Start ¶
func (sc ServerConfig) Start(ctx context.Context, app *App) error
Start starts the HTTP server and blocks until ctx is cancelled, at which point it initiates a graceful shutdown — waiting for in-flight requests to complete before returning.
func (ServerConfig) StartTLS ¶
func (sc ServerConfig) StartTLS(ctx context.Context, app *App) error
StartTLS starts an HTTPS server using the certificate and key files configured in ServerConfig. Blocks and shuts down gracefully on ctx cancellation, same as ServerConfig.Start.
type WSConfig ¶ added in v0.6.0
type WSConfig struct {
// Subprotocols is the list of supported WebSocket subprotocols.
// The server negotiates the best match with the client's
// Sec-WebSocket-Protocol header.
Subprotocols []string
// WriteTimeout is the maximum duration allowed for a single write
// operation. A zero value means no timeout.
WriteTimeout time.Duration
// Origins is the list of allowed Origin header values for the handshake.
// Requests with an origin not in this list are rejected with 403.
// If empty, all origins are permitted.
Origins []string
// AllowEmptyOrigin permits WebSocket upgrade requests that carry no
// Origin header. Useful for non-browser clients. Default: false.
AllowEmptyOrigin bool
// MaxMessageSize is the maximum allowed incoming message size in bytes.
// Messages exceeding this limit cause the connection to be closed.
// A zero value means no limit.
MaxMessageSize uint64
}
WSConfig holds configuration options for a WebSocket endpoint. All fields are optional; unset fields fall back to sensible defaults.
type WSConn ¶ added in v0.6.0
type WSConn struct {
// contains filtered or unexported fields
}
WSConn is an Aero WebSocket connection. It wraps the underlying low-level connection and provides a high-level API for reading, writing, and connection-scoped storage. Obtain a WSConn inside a WebSocketHandler.
func (*WSConn) Close ¶ added in v0.6.0
Close sends a normal closure frame and closes the underlying connection.
func (*WSConn) CloseWithReason ¶ added in v0.6.0
func (ws *WSConn) CloseWithReason(code websocket.CloseStatusCode, reason string) error
CloseWithReason sends a close frame with the given status code and reason string before closing the connection.
ws.CloseWithReason(websocket.CloseNormalClosure, "bye")
func (*WSConn) Locals ¶ added in v0.6.0
Locals stores or retrieves a connection-scoped value by key. When called with a value argument, it sets the key and returns the new value. When called with the key only, it returns the current value or nil.
ws.Locals("userID", 42)
id := ws.Locals("userID").(int)
func (*WSConn) ReadMessage ¶ added in v0.6.0
ReadMessage reads the next message from the connection. Returns the message type (aero.TextMessage or aero.BinaryMessage), the payload, and any error. A non-nil error typically means the connection was closed or the message exceeded [WSConfig.MaxMessageSize].
type WebSocketHandler ¶ added in v0.6.0
type WebSocketHandler func(*WSConn)
WebSocketHandler is the function signature for WebSocket connection handlers. The connection is automatically closed when the handler returns.
aero.WebSocket(func(ws *aero.WSConn) {
for {
mt, msg, err := ws.ReadMessage()
if err != nil {
break
}
ws.WriteMessage(mt, msg)
}
})
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
color
Package color provides ANSI escape code constants and helper functions for writing colored text to the terminal.
|
Package color provides ANSI escape code constants and helper functions for writing colored text to the terminal. |
|
middleware
|
|
|
Package websocket provides a low-level, zero-dependency WebSocket implementation following RFC 6455.
|
Package websocket provides a low-level, zero-dependency WebSocket implementation following RFC 6455. |