Middleware
Middleware wraps a handler to execute code before or after the request is processed. It is useful for authentication, logging, rate limiting, and recovery.
Middleware Pipeline
Section titled “Middleware Pipeline”Request ↓┌─────────────────┐│ Logger │ ← log start time│ ┌───────────┐ ││ │ Recovery │ │ ← catch panics│ │ ┌───────┐ │ ││ │ │Handler│ │ │ ← process request│ │ └───────┘ │ ││ └───────────┘ │└─────────────────┘ ↓ResponseMiddleware is executed in registration order. Each middleware can either pass the request to the next handler or short-circuit the chain (e.g., return a 401 for unauthorized requests).
Built-in Middleware
Section titled “Built-in Middleware”import "goigniter/system/middleware"
func main() { app := core.New()
// Log every request (method, path, duration) app.Use(middleware.Logger())
// Catch panics to prevent server crash app.Use(middleware.Recovery())
// Handle CORS for API app.Use(middleware.CORS())
// Rate limit per IP app.Use(middleware.RateLimit(100, time.Minute))
app.Run(":8080")}Logger
Section titled “Logger”Logs every request to console:
app.Use(middleware.Logger())
// Output:// [GET] /products 1.234ms <nil>// [POST] /products 5.678ms <nil>Custom configuration:
app.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ Format: "[%s] %s %v", SkipPaths: []string{"/health", "/metrics"},}))Recovery
Section titled “Recovery”Catches panics and returns a 500 error instead of crashing:
app.Use(middleware.Recovery())Handles Cross-Origin Resource Sharing for APIs:
app.Use(middleware.CORS())RateLimit
Section titled “RateLimit”Limits requests per IP address:
app.Use(middleware.RateLimit(100, time.Minute)) // 100 requests per minute per IPGlobal vs Group Middleware
Section titled “Global vs Group Middleware”Global
Section titled “Global”Applies to all routes:
app.Use(middleware.Logger()) // All requests loggedapp.Use(middleware.Recovery()) // All panics caughtApplies only to routes in a specific group:
// Public routes - no authapp.GET("/", homeHandler)app.GET("/products", listProducts)
// Admin routes - with authadmin := app.Group("/admin", AuthMiddleware())admin.GET("/dashboard", dashboard) // Requires loginadmin.GET("/users", adminUsers) // Requires loginCustom Middleware
Section titled “Custom Middleware”package middleware
import "goigniter/system/core"
func AuthMiddleware() core.Middleware { return func(next core.HandlerFunc) core.HandlerFunc { return func(c *core.Context) error { // Check session or token userID := getSessionUserID(c)
if userID == 0 { // Not logged in, redirect to login return c.Redirect(302, "/login") }
// Store user info for the handler c.Set("user_id", userID)
// Proceed to the next handler return next(c) } }}Usage:
// Group middlewareadmin := app.Group("/admin", AuthMiddleware())
// Per-route middlewareapp.GET("/profile", AuthMiddleware()(profileHandler))Middleware with Configuration
Section titled “Middleware with Configuration”type AuthConfig struct { LoginURL string ExcludePath []string}
func AuthWithConfig(config AuthConfig) core.Middleware { skipPaths := make(map[string]bool) for _, path := range config.ExcludePath { skipPaths[path] = true }
return func(next core.HandlerFunc) core.HandlerFunc { return func(c *core.Context) error { if skipPaths[c.Path()] { return next(c) }
if !isLoggedIn(c) { return c.Redirect(302, config.LoginURL) }
return next(c) } }}
// Usageapp.Use(AuthWithConfig(AuthConfig{ LoginURL: "/auth/login", ExcludePath: []string{"/", "/about", "/contact"},}))Controller-Level Middleware
Section titled “Controller-Level Middleware”Define middleware that applies to all methods in a controller:
type Admin struct { core.Controller}
func (a *Admin) Middleware() []core.Middleware { return []core.Middleware{ AuthMiddleware(), AdminOnlyMiddleware(), }}
func (a *Admin) Index() { // Already authenticated and verified as admin a.Ctx.View("admin/dashboard", core.Map{})}Per-Method Middleware
Section titled “Per-Method Middleware”Apply middleware to specific methods:
type Product struct { core.Controller}
func (p *Product) MiddlewareFor() map[string][]core.Middleware { return map[string][]core.Middleware{ "Store": {AuthMiddleware()}, "Update": {AuthMiddleware()}, "Delete": {AuthMiddleware(), AdminOnly()}, }}
func (p *Product) Index() { // Public - no auth}
func (p *Product) Store() { // Requires login}
func (p *Product) Delete() { // Requires login + admin}Next: Template Engine for rendering HTML views.