router

package
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: May 4, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package router defines the HTTP routing abstraction used by Aegis.

Index

Constants

View Source
const MaxRequestBodySize = 1 << 20 // 1MB

MaxRequestBodySize is the default maximum request body size (1MB).

This limit prevents denial-of-service attacks via extremely large request bodies that could exhaust server memory or network bandwidth.

Adjust this based on your use case:

  • API endpoints: 1MB is usually sufficient
  • File uploads: Increase to 10MB or more
  • Webhooks: May need larger limits depending on payload size

Variables

This section is empty.

Functions

func DefaultSecurityMiddleware

func DefaultSecurityMiddleware(next http.Handler) http.Handler

DefaultSecurityMiddleware applies a standard set of security protections.

This is a convenience middleware that combines:

  • SecurityHeadersMiddleware (OWASP security headers)
  • MaxRequestBodyMiddleware with 1MB limit (DoS protection)

This provides a good security baseline for most applications. Apply this middleware early in your middleware chain (before authentication) to protect all routes.

Usage:

r := chi.NewRouter()
r.Use(router.DefaultSecurityMiddleware)
r.Use(core.AegisContextMiddleware())
// ... rest of your routes

func JoinPath added in v1.6.0

func JoinPath(prefix, sub string) string

JoinPath concatenates a prefix and a sub-path, normalising the boundary between them so e.g. "/auth/" + "/jwt" yields "/auth/jwt" rather than "/auth//jwt". An empty input is treated as "" — there is no implicit "/" prefix, so callers retain full control over absolute vs relative paths.

func MaxRequestBodyMiddleware

func MaxRequestBodyMiddleware(maxBytes int64) func(http.Handler) http.Handler

MaxRequestBodyMiddleware limits the size of HTTP request bodies.

This middleware wraps the request body with http.MaxBytesReader, which enforces a size limit. If a request exceeds the limit, reading the body will fail and the connection will be closed.

Benefits:

  • Prevents memory exhaustion from large requests
  • Prevents network bandwidth abuse
  • Protects against ZIP bomb attacks
  • Limits upload file sizes

Parameters:

  • maxBytes: Maximum allowed request body size in bytes

Usage:

// Apply 1MB limit to all routes
r.Use(router.MaxRequestBodyMiddleware(1 << 20))

// Apply 10MB limit for file upload routes
uploadRouter.Use(router.MaxRequestBodyMiddleware(10 << 20))

func NormalizePathToOpenAPI

func NormalizePathToOpenAPI(path string) string

NormalizePathToOpenAPI converts router parameter syntax to OpenAPI path syntax.

Different HTTP routers use different syntax for path parameters:

  • Chi, Gin, Echo: /users/:id/posts/:postId
  • Gorilla Mux: /users/{id}/posts/{postId}
  • OpenAPI spec: /users/{id}/posts/{postId}

This function normalizes paths from :param syntax (chi/gin/echo) to {param} syntax (OpenAPI spec) for automatic API documentation generation.

Conversion rules:

  • :id → {id}
  • :userId → {userId}
  • :post_id → {post_id}
  • Parameter names can contain: a-z, A-Z, 0-9, _

Examples:

NormalizePathToOpenAPI("/users/:id")
// Returns: "/users/{id}"

NormalizePathToOpenAPI("/organizations/:orgId/members/:userId")
// Returns: "/organizations/{orgId}/members/{userId}"

NormalizePathToOpenAPI("/static/file.css")
// Returns: "/static/file.css" (unchanged, no parameters)

func SecurityHeadersMiddleware

func SecurityHeadersMiddleware(next http.Handler) http.Handler

SecurityHeadersMiddleware adds security headers to all HTTP responses.

This middleware implements OWASP security best practices by adding headers that protect against common web vulnerabilities:

Headers added:

  • X-Content-Type-Options: nosniff Prevents MIME type sniffing (prevents browsers from interpreting files as different MIME type) Protects against: Drive-by download attacks

  • X-Frame-Options: DENY Prevents the page from being embedded in <iframe>, <frame>, or <object> Protects against: Clickjacking attacks

  • X-XSS-Protection: 1; mode=block Enables browser XSS filter (legacy, mostly replaced by CSP) Protects against: Reflected XSS attacks in older browsers

  • Referrer-Policy: strict-origin-when-cross-origin Controls how much referrer information is sent with requests Protects against: Information leakage via Referer header

  • Content-Security-Policy: default-src 'self' Basic CSP that only allows resources from the same origin Protects against: XSS, data injection, malicious scripts Note: This is a basic policy - override with custom CSP for your needs

Usage:

r.Use(router.SecurityHeadersMiddleware)

Note: The CSP header can be customized by setting it before this middleware runs, or by using a custom middleware that overrides it.

Types

type ConflictFunc added in v1.6.0

type ConflictFunc func(method, path, newOwner, prevOwner string)

ConflictFunc is invoked whenever the registry observes a second registration of the same (method, path) under a different owner. It is informational — the registry still records the duplicate entry and forwards the registration to the underlying router. Callers wire this to their logger of choice.

Passing nil disables conflict reporting.

type GroupRouter

type GroupRouter interface {
	// GET registers a GET route handler within this group
	GET(path string, handler http.HandlerFunc)

	// POST registers a POST route handler within this group
	POST(path string, handler http.HandlerFunc)

	// PUT registers a PUT route handler within this group
	PUT(path string, handler http.HandlerFunc)

	// PATCH registers a PATCH route handler within this group
	PATCH(path string, handler http.HandlerFunc)

	// DELETE registers a DELETE route handler within this group
	DELETE(path string, handler http.HandlerFunc)

	// Use adds middleware to this group only
	// Middleware is scoped to this group and does not affect parent or sibling routes
	Use(middleware func(http.Handler) http.Handler)

	// Group creates a nested sub-group within this group.
	// Nested groups inherit the parent's prefix and allow further
	// organization of routes.
	Group(path string, groupName string) GroupRouter
}

GroupRouter represents a sub-router for grouping related routes.

GroupRouter provides the same HTTP method registration as Router, but routes are prefixed with the group's path.

Example:

adminGroup := router.Group("/admin", "Admin")
adminGroup.Use(requireAdminMiddleware)
adminGroup.GET("/users", listUsersHandler)
adminGroup.DELETE("/users/:id", deleteUserHandler)

type Registry added in v1.6.0

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

Registry records every route mounted through a Recorder. It exists for two reasons:

  1. Conflict detection. Most underlying routers (chi, mux, gin) silently accept a duplicate (method, path) registration and either overwrite the previous handler or panic at runtime. The registry surfaces these collisions through the supplied ConflictFunc as soon as the second registration happens, naming both owners.

  2. Introspection. Tools like an OpenAPI generator, an audit dashboard, or a debug endpoint want a complete inventory of the HTTP surface area of the application without re-implementing route tracking.

The Registry has no opinion about routing semantics — it only observes.

func NewRegistry added in v1.6.0

func NewRegistry() *Registry

NewRegistry returns an empty registry. A single registry is typically shared across every Recorder created during application startup.

func (*Registry) Routes added in v1.6.0

func (r *Registry) Routes() []RouteEntry

Routes returns a snapshot of all recorded routes, sorted by path then method. The returned slice is detached from the registry; callers may mutate it freely.

type RouteEntry added in v1.6.0

type RouteEntry struct {
	Method string
	Path   string
	Owner  string
}

RouteEntry describes a single (method, path) registration captured by the route registry. Owner identifies the logical source of the route (e.g. a plugin name, or "core" for framework-level routes).

type Router

type Router interface {
	// GET registers a GET route handler
	GET(path string, handler http.HandlerFunc)

	// POST registers a POST route handler
	POST(path string, handler http.HandlerFunc)

	// PUT registers a PUT route handler
	PUT(path string, handler http.HandlerFunc)

	// PATCH registers a PATCH route handler
	PATCH(path string, handler http.HandlerFunc)

	// DELETE registers a DELETE route handler
	DELETE(path string, handler http.HandlerFunc)

	// Use adds middleware to the router
	// Middleware should follow the func(http.Handler) http.Handler pattern
	Use(middleware func(http.Handler) http.Handler)

	// ServeHTTP implements http.Handler for serving requests
	ServeHTTP(w http.ResponseWriter, r *http.Request)

	// Group creates a sub-router with a prefix for grouping related routes.
	// Routes mounted to the returned GroupRouter will be prefixed with the given path.
	// The groupName is used for organizational purposes.
	//
	// Example:
	//   jwtGroup := router.Group("/jwt", "JWT")
	//   jwtGroup.POST("/token", tokenHandler)     // Mounted at /jwt/token
	//   jwtGroup.POST("/refresh", refreshHandler) // Mounted at /jwt/refresh
	Group(path string, groupName string) GroupRouter
}

Router is the interface for HTTP routers in Aegis.

This abstraction allows Aegis to work with different HTTP routing libraries (chi, mux, gin, echo, etc.) without coupling to a specific implementation.

Implementations must support:

  • Standard HTTP methods (GET, POST, PUT, PATCH, DELETE)
  • Middleware chain using standard http.Handler interface
  • http.Handler compliance for ServeHTTP
  • Route grouping for organizing related routes

func NewRecorder added in v1.6.0

func NewRecorder(inner Router, reg *Registry, owner, prefix string, onConflict ConflictFunc) Router

NewRecorder wraps inner so every route registered through the returned Router (and any GroupRouter derived from it) is recorded in reg under the given owner. prefix is the absolute path that will be prepended to each registration before recording (so an OpenAPI list shows fully qualified URLs); pass "" if the caller already passes absolute paths.

onConflict is called for any duplicate (method, path) registered under a different owner; pass nil to disable conflict reporting.

Directories

Path Synopsis
Package defaults provides the core Aegis route mounting with OpenAPI documentation.
Package defaults provides the core Aegis route mounting with OpenAPI documentation.
Package routers provides router adapters for the Aegis authentication framework.
Package routers provides router adapters for the Aegis authentication framework.

Jump to

Keyboard shortcuts

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