rig

package module
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 8 Imported by: 2

README

Rig

Home  /

 

Rig is a lightweight HTTP framework for Go that wraps net/http with zero external dependencies. Built for Go 1.22+, it provides the ergonomics of popular frameworks while staying true to the standard library.

 

Go Reference Go Tests Go Report Card GitHub Tag License

 

Features

  • Zero Dependencies - Only the Go standard library (core package)
  • Go 1.22+ Pattern Matching - Full support for method routing and path parameters
  • Middleware - Global, group, and per-route middleware with onion-style execution
  • Route Groups - Organize routes with shared prefixes and middleware
  • JSON Handling - Bind, BindStrict, and JSON response helpers
  • Static Files - Serve directories with a single line
  • Production Middleware - Built-in Recover and CORS middleware
  • Health Checks - Liveness and readiness probes for Kubernetes
  • HTML Templates - Template rendering with layouts, partials, embed.FS, and content negotiation (render/ sub-package)
  • Authentication - API Key and Bearer Token middleware (auth/ sub-package)
  • Request ID - ULID-based request tracking (requestid/ sub-package)
  • Logging - Structured request logging with JSON support (logger/ sub-package)
  • Swagger UI - Optional sub-package for API documentation
  • Type-Safe Context - Generic GetType[T] for dependency injection
  • 99%+ Test Coverage - Battle-tested and production-ready

 

🔝 back to top

 

Installation

go get github.com/cloudresty/rig

Requires Go 1.22 or later.

 

🔝 back to top

 

Quick Start

package main

import (
    "net/http"

    "github.com/cloudresty/rig"
)

func main() {
    r := rig.New()

    // Add middleware
    r.Use(rig.Recover())
    r.Use(rig.DefaultCORS())

    // Simple route
    r.GET("/", func(c *rig.Context) error {
        return c.JSON(http.StatusOK, map[string]string{
            "message": "Hello, World!",
        })
    })

    // Path parameters (Go 1.22+)
    r.GET("/users/{id}", func(c *rig.Context) error {
        id := c.Param("id")
        return c.JSON(http.StatusOK, map[string]string{
            "user_id": id,
        })
    })

    http.ListenAndServe(":8080", r)
}

 

🔝 back to top

 

Route Groups

Organize routes with shared prefixes and middleware:

r := rig.New()

// API group with authentication middleware
api := r.Group("/api")
api.Use(authMiddleware)

api.GET("/users", listUsers)       // GET /api/users
api.POST("/users", createUser)     // POST /api/users
api.GET("/users/{id}", getUser)    // GET /api/users/{id}

// Nested groups
v1 := api.Group("/v1")
v1.GET("/status", getStatus)       // GET /api/v1/status

 

🔝 back to top

 

Middleware

Middleware follows the decorator pattern with onion-style execution:

// Custom middleware
func Logger() rig.MiddlewareFunc {
    return func(next rig.HandlerFunc) rig.HandlerFunc {
        return func(c *rig.Context) error {
            start := time.Now()
            err := next(c)
            log.Printf("%s %s %v", c.Method(), c.Path(), time.Since(start))
            return err
        }
    }
}

// Apply middleware
r.Use(rig.Recover())    // Global - catches panics
r.Use(rig.DefaultCORS()) // Global - enables CORS
r.Use(Logger())          // Global - logs requests

 

Built-in Middleware
Middleware Description
Recover() Catches panics and returns a 500 JSON error
DefaultCORS() Permissive CORS (allows all origins)
CORS(config) Configurable CORS with specific origins/methods/headers

 

Additional middleware sub-packages (see sections below):

Package Description
auth/ API Key and Bearer Token authentication
requestid/ ULID-based request ID generation
logger/ Structured request logging (text/JSON)

 

🔝 back to top

 

Request Handling

Path Parameters
r.GET("/users/{id}", func(c *rig.Context) error {
    id := c.Param("id")
    // ...
})

 

Query Parameters
r.GET("/search", func(c *rig.Context) error {
    q := c.Query("q")                    // Single value
    tags := c.QueryArray("tag")          // Multiple values: ?tag=a&tag=b
    page := c.QueryDefault("page", "1")  // With default
    // ...
})

 

JSON Body
r.POST("/users", func(c *rig.Context) error {
    var user User
    if err := c.Bind(&user); err != nil {
        return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
    }
    // Use c.BindStrict(&user) to reject unknown fields
    // ...
})

 

Form Data
r.POST("/login", func(c *rig.Context) error {
    username := c.FormValue("username")      // Body takes precedence over query
    password := c.PostFormValue("password")  // Body only
    // ...
})

 

🔝 back to top

 

Response Helpers

// JSON response
c.JSON(http.StatusOK, data)

// String response
c.WriteString("Hello")

// Redirect
c.Redirect(http.StatusFound, "/new-location")

// Serve a file
c.File("./reports/monthly.pdf")

// Raw bytes
c.Data(http.StatusOK, "image/png", pngBytes)

// Set status only
c.Status(http.StatusNoContent)

 

🔝 back to top

 

Static Files

Serve a directory of static files:

r.Static("/assets", "./public")
// GET /assets/css/style.css → serves ./public/css/style.css

 

🔝 back to top

 

Dependency Injection

Use the context store for request-scoped values:

// Middleware: inject dependencies
func InjectDB(db *Database) rig.MiddlewareFunc {
    return func(next rig.HandlerFunc) rig.HandlerFunc {
        return func(c *rig.Context) error {
            c.Set("db", db)
            return next(c)
        }
    }
}

// Handler: retrieve with type safety
r.GET("/users", func(c *rig.Context) error {
    db, err := rig.GetType[*Database](c, "db")
    if err != nil {
        return err
    }
    // Use db...
})

 

🔝 back to top

 

CORS Configuration

// Permissive (all origins)
r.Use(rig.DefaultCORS())

// Restrictive with exact origins
r.Use(rig.CORS(rig.CORSConfig{
    AllowOrigins: []string{"https://myapp.com", "https://admin.myapp.com"},
    AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
    AllowHeaders: []string{"Content-Type", "Authorization"},
}))

// Wildcard subdomain support
r.Use(rig.CORS(rig.CORSConfig{
    AllowOrigins: []string{
        "https://*.myapp.com",           // Matches any subdomain
        "https://*.staging.myapp.com",   // Matches nested subdomains
        "https://api.production.com",    // Exact match also works
    },
    AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
    AllowHeaders: []string{"Content-Type", "Authorization"},
}))

 

AllowOrigins patterns:

Pattern Matches Does Not Match
"*" All origins -
"https://example.com" Exact match only https://sub.example.com
"https://*.example.com" https://app.example.com, https://a.b.example.com https://example.com, http://app.example.com

 

🔝 back to top

 

Health Checks

Rig provides an opt-in health utility for liveness and readiness probes, perfect for Kubernetes deployments:

func main() {
    r := rig.New()
    db := connectDB()

    // Create the Health manager
    health := rig.NewHealth()

    // Add readiness check (don't send traffic if DB is down)
    health.AddReadinessCheck("database", func() error {
        return db.Ping()
    })

    // Add liveness check (is the app running?)
    health.AddLivenessCheck("ping", func() error {
        return nil // Always healthy
    })

    // Mount the handlers (user chooses the paths)
    h := r.Group("/health")
    h.GET("/live", health.LiveHandler())
    h.GET("/ready", health.ReadyHandler())

    r.Run(":8080")
}

 

Response format:

// GET /health/ready (all checks pass)
{ "status": "OK", "checks": { "database": "OK" } }

// GET /health/ready (a check fails)
{ "status": "Service Unavailable", "checks": { "database": "FAIL: connection refused" } }

 

Method Description
NewHealth() Creates a new Health manager
AddReadinessCheck(name, fn) Adds a check for traffic readiness (DB, Redis, etc.)
AddLivenessCheck(name, fn) Adds a check for app liveness (deadlock detection, etc.)
LiveHandler() Returns a handler for liveness probes
ReadyHandler() Returns a handler for readiness probes

 

🔝 back to top

 

Swagger UI

Rig provides optional Swagger UI support via a separate sub-package to keep the core framework dependency-free:

go get github.com/cloudresty/rig/swagger

 

Basic Usage with swaggo/swag
package main

import (
    "github.com/cloudresty/rig"
    "github.com/cloudresty/rig/swagger"
    _ "myapp/docs" // Generated by: swag init
)

func main() {
    r := rig.New()

    // Your API routes
    r.GET("/api/v1/users", handleUsers)

    // Register Swagger UI at /docs/
    sw := swagger.NewFromSwag("swagger")
    sw.Register(r, "/docs")

    r.Run(":8080")
}
// Access Swagger UI at http://localhost:8080/docs/

 

Usage with Custom Spec
spec := `{"openapi":"3.0.0","info":{"title":"My API","version":"1.0"}}`
sw := swagger.New(spec).
    WithTitle("My API Documentation").
    WithDocExpansion("list")
sw.Register(r, "/api-docs")

 

Usage with Route Groups
api := r.Group("/api/v1")
sw := swagger.NewFromSwag("swagger")
sw.RegisterGroup(api, "/docs")
// Access at /api/v1/docs/

 

Method Description
New(specJSON) Creates Swagger UI with a JSON spec string
NewFromSwag(name) Creates Swagger UI from swaggo/swag registered spec
WithTitle(title) Sets the page title
WithDeepLinking(bool) Enables/disables URL deep linking (default: true)
WithDocExpansion(mode) Sets expansion mode: "list", "full", "none"
Register(router, path) Registers routes on a Router
RegisterGroup(group, path) Registers routes on a RouteGroup

 

🔝 back to top

 

Authentication Middleware

The auth/ sub-package provides API Key and Bearer Token authentication:

go get github.com/cloudresty/rig/auth

 

API Key Authentication
import "github.com/cloudresty/rig/auth"

// Simple: validate against a list of keys
api := r.Group("/api")
api.Use(auth.APIKeySimple("key1", "key2", "key3"))

// Advanced: custom validation with identity
api.Use(auth.APIKey(auth.APIKeyConfig{
    Name:   "X-API-Key",        // Header name (default)
    Source: "header",           // "header" or "query"
    Validator: func(key string) (identity string, valid bool) {
        if key == os.Getenv("API_KEY") {
            return "my-service", true
        }
        return "", false
    },
}))

// In handlers, get the authenticated identity
r.GET("/profile", func(c *rig.Context) error {
    identity := auth.GetIdentity(c)  // Returns identity from Validator
    method := auth.GetMethod(c)      // Returns "api_key" or "bearer"
    return c.JSON(http.StatusOK, map[string]string{"user": identity})
})

 

Bearer Token Authentication
api.Use(auth.Bearer(auth.BearerConfig{
    Realm: "API",
    Validator: func(token string) (identity string, valid bool) {
        // Validate JWT or lookup token
        claims, err := validateJWT(token)
        if err != nil {
            return "", false
        }
        return claims.UserID, true
    },
}))

 

Function Description
APIKeySimple(keys...) Simple API key validation (constant-time comparison)
APIKey(config) Configurable API key middleware
Bearer(config) Bearer token middleware (RFC 6750)
GetIdentity(c) Get authenticated identity from context
GetMethod(c) Get auth method ("api_key" or "bearer")
IsAuthenticated(c) Check if request is authenticated

 

🔝 back to top

 

Request ID Middleware

The requestid/ sub-package generates unique request IDs using ULIDs:

go get github.com/cloudresty/rig/requestid

 

import "github.com/cloudresty/rig/requestid"

r := rig.New()

// Add request ID middleware (generates ULID for each request)
r.Use(requestid.New())

// With custom configuration
r.Use(requestid.New(requestid.Config{
    Header:     "X-Request-ID",  // Response header (default)
    TrustProxy: true,            // Trust incoming X-Request-ID header
    Generator: func() (string, error) {
        return uuid.New().String(), nil  // Use UUID instead of ULID
    },
}))

// In handlers, get the request ID
r.GET("/", func(c *rig.Context) error {
    reqID := requestid.Get(c)
    return c.JSON(http.StatusOK, map[string]string{
        "request_id": reqID,
    })
})

 

Function Description
New() Create middleware with default config
New(config) Create middleware with custom config
Get(c) Get request ID from context

 

🔝 back to top

 

Logger Middleware

The logger/ sub-package provides structured request logging:

go get github.com/cloudresty/rig/logger

 

import "github.com/cloudresty/rig/logger"

r := rig.New()

// Add request ID first (logger will include it)
r.Use(requestid.New())

// Add logger middleware
r.Use(logger.New(logger.Config{
    Format:    logger.FormatJSON,              // FormatText or FormatJSON
    Output:    os.Stdout,                       // io.Writer
    SkipPaths: []string{"/health", "/ready"},  // Don't log these paths
}))

 

Text format output:

2024/01/15 10:30:45 | 200 |    1.234ms | 192.168.1.1 | GET /api/users | req_id: 01HQ...

JSON format output:

{"time":"2024-01-15T10:30:45Z","status":200,"latency":"1.234ms","latency_ms":1.234,"client_ip":"192.168.1.1","method":"GET","path":"/api/users","request_id":"01HQ..."}

 

Option Description
Format FormatText (default) or FormatJSON
Output io.Writer for log output (default: os.Stdout)
SkipPaths Paths to exclude from logging (e.g., health checks)

 

🔝 back to top

 

HTML Template Rendering

The render sub-package provides HTML template rendering with layouts, partials, hot reloading, and content negotiation.

go get github.com/cloudresty/rig/render

 

Basic Usage
import (
    "github.com/cloudresty/rig"
    "github.com/cloudresty/rig/render"
)

func main() {
    engine := render.New(render.Config{
        Directory: "./templates",
    })

    r := rig.New()
    r.Use(engine.Middleware())

    r.GET("/", func(c *rig.Context) error {
        return render.HTML(c, http.StatusOK, "home", map[string]any{
            "Title": "Welcome",
            "User":  "John",
        })
    })

    r.Run(":8080")
}

 

🔝 back to top

 

Embedded Templates (embed.FS)

For single-binary deployments, embed templates directly into your Go binary:

import (
    "embed"
    "github.com/cloudresty/rig/render"
)

//go:embed templates/*
var templateFS embed.FS

func main() {
    engine := render.New(render.Config{
        FileSystem: templateFS,
        Directory:  "templates",
    })
    // Templates are now compiled into the binary!
}

 

🔝 back to top

 

With Layouts
engine := render.New(render.Config{
    Directory: "./templates",
    Layout:    "layouts/base", // Base layout template
})

 

Layout template (templates/layouts/base.html):

<!DOCTYPE html>
<html>
<head><title>{{.Data.Title}}</title></head>
<body>
    <header>My Site</header>
    <main>{{.Content}}</main>
    <footer>© 2026</footer>
</body>
</html>

 

Page template (templates/home.html):

<h1>Welcome, {{.User}}!</h1>

 

Layout Data Access:

In layouts, data is available via {{.Data}} (works with both structs and maps):

Expression Description
{{.Content}} Rendered page content
{{.Data.Title}} Access data fields (works with structs!)
{{.Title}} Direct access (backward compatible with maps)

 

🔝 back to top

 

Partials

Templates starting with underscore (_) are automatically treated as partials and available to all templates:

templates/
├── _sidebar.html    ← Partial (available everywhere)
├── _footer.html     ← Partial (available everywhere)
├── home.html
└── about.html

 

Use partials in any template:

<div class="page">
    {{template "_sidebar" .}}
    <main>{{.Content}}</main>
    {{template "_footer" .}}
</div>

 

🔝 back to top

 

JSON and XML Responses

Render JSON or XML directly without templates:

// JSON response
r.GET("/api/users", func(c *rig.Context) error {
    return render.JSON(c, http.StatusOK, users)
})

// XML response
r.GET("/api/users.xml", func(c *rig.Context) error {
    return render.XML(c, http.StatusOK, users)
})

 

🔝 back to top

 

Content Negotiation

Use Auto() to automatically select the response format based on the Accept header:

r.GET("/users", func(c *rig.Context) error {
    // Returns HTML for browsers, JSON for API clients
    return render.Auto(c, http.StatusOK, "users/list", users)
})

 

Accept Header Response Format
application/json JSON
application/xml or text/xml XML
text/html or other HTML (if template provided)
No template provided JSON (fallback)

 

🔝 back to top

 

Error Pages (Production)

Use HTMLSafe() to automatically render a pretty error page when template rendering fails:

r.GET("/page", func(c *rig.Context) error {
    return render.HTMLSafe(c, http.StatusOK, "page", data, "errors/500")
})

 

If "page" fails to render, it automatically falls back to "errors/500" with error details:

<!-- templates/errors/500.html -->
<h1>Something went wrong</h1>
<p>Error: {{.Error}}</p>
<p>Status: {{.StatusCode}}</p>

 

🔝 back to top

 

Development Mode

Enable hot reloading during development:

engine := render.New(render.Config{
    Directory: "./templates",
    DevMode:   true, // Reloads templates on each request
})

 

🔝 back to top

 

Custom Template Functions
engine := render.New(render.Config{
    Directory: "./templates",
    Funcs: template.FuncMap{
        "upper": strings.ToUpper,
        "formatDate": func(t time.Time) string {
            return t.Format("Jan 2, 2006")
        },
    },
})
// Or use chained methods:
engine.AddFunc("lower", strings.ToLower)

 

Use in templates: {{upper .Name}} or {{formatDate .CreatedAt}}

 

🔝 back to top

 

Built-in Functions
Function Description Usage
safe Render trusted HTML without escaping {{safe .RawHTML}}
safeAttr Render trusted HTML attribute {{safeAttr .Attr}}
safeURL Render trusted URL {{safeURL .Link}}
dump Debug helper - outputs data as formatted JSON {{dump .}}

 

The dump function is invaluable during development:

<!-- Debug: see what data was passed to the template -->
{{dump .Data}}

Outputs:

<pre>{
  "Title": "My Page",
  "User": {
    "Name": "John"
  }
}</pre>

 

🔝 back to top

 

Using Sprig Functions

For 100+ additional template functions (string manipulation, math, dates, etc.), integrate Sprig:

import "github.com/Masterminds/sprig/v3"

engine := render.New(render.Config{
    Directory: "./templates",
})
engine.AddFuncs(sprig.FuncMap())

 

Now you can use functions like {{.Name | upper}}, {{now | date "2006-01-02"}}, and many more.

 

🔝 back to top

 

Custom Delimiters (Vue.js / Angular / Alpine.js)

When using frontend frameworks that also use {{ }} syntax, configure custom delimiters:

engine := render.New(render.Config{
    Directory: "./templates",
    Delims:    []string{"[[", "]]"}, // Use [[ ]] for Go templates
})

 

Now your templates can mix Go and Vue/Angular syntax:

<div>
    <!-- Go template (rendered on server) -->
    <h1>[[ .Title ]]</h1>

    <!-- Vue.js binding (rendered on client) -->
    <p>{{ message }}</p>
</div>

 

🔝 back to top

 

Debugging

List loaded templates and partials:

engine.TemplateNames() // Returns all template names
engine.PartialNames()  // Returns all partial names (files starting with _)

 

🔝 back to top

 

Examples

The examples/ directory contains runnable examples:

Example Description
basic-api REST API with middleware, dependency injection, and route groups
health-checks Kubernetes-style liveness and readiness probes
swagger-ui API with integrated Swagger UI documentation
auth-middleware API Key authentication using the auth/ package
logging Request logging with request ID tracking
render-templates HTML templates with layouts, partials, and content negotiation

 

🔝 back to top

 

API Reference

Context Methods
Method Description
Param(name) Get path parameter
Query(key) Get query parameter
QueryDefault(key, def) Get query parameter with default
QueryArray(key) Get all values for a query parameter
FormValue(key) Get form value (body precedence)
PostFormValue(key) Get form value (body only)
GetHeader(key) Get request header
SetHeader(key, value) Set response header
Bind(v) Decode JSON body
BindStrict(v) Decode JSON body (reject unknown fields)
JSON(code, v) Send JSON response
Status(code) Set status code
Redirect(code, url) Send redirect
File(path) Serve a file
Data(code, contentType, data) Send raw bytes
Set(key, value) Store request-scoped value
Get(key) Retrieve stored value
MustGet(key) Retrieve stored value (panics if missing)
Context() Get context.Context
SetContext(ctx) Set context.Context
Request() Get *http.Request
Writer() Get http.ResponseWriter

 

Router Methods
Method Description
New() Create a new router
Use(middleware...) Add global middleware
Handle(pattern, handler) Register a handler
GET/POST/PUT/DELETE/PATCH/OPTIONS/HEAD(path, handler) Register method-specific handler
Group(prefix) Create a route group
Static(path, root) Serve static files
ServeHTTP(w, r) Implement http.Handler

 

🔝 back to top

 

License

This project is licensed under the MIT License - see the LICENSE file for details.

 

🔝 back to top

 

 


Cloudresty

Website  |  LinkedIn  |  BlueSky  |  GitHub  |  Docker Hub

© Cloudresty - All rights reserved

 

Documentation

Overview

Package rig provides a thin, zero-dependency wrapper around the Go standard library's net/http package. It offers ergonomic benefits similar to frameworks like Gin or Echo while relying purely on the Go standard library.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultErrorHandler

func DefaultErrorHandler(c *Context, err error)

DefaultErrorHandler is the default error handler that writes a 500 Internal Server Error response when a handler returns an error.

func GetType

func GetType[T any](c *Context, key string) (T, error)

GetType retrieves a value from the context's key-value store and asserts its type safely using generics. This is the recommended way to retrieve typed values as it avoids panics from incorrect type assertions.

Example:

db, err := rig.GetType[*Database](c, "db")
if err != nil {
    return err
}
db.Query(...)

Types

type CORSConfig

type CORSConfig struct {
	// AllowOrigins is a list of origins that are allowed to access the resource.
	// Supports three formats:
	//   - "*" to allow all origins
	//   - Exact match: "https://example.com"
	//   - Wildcard subdomain: "https://*.example.com" (matches any subdomain)
	AllowOrigins []string

	// AllowMethods is a list of methods allowed when accessing the resource.
	AllowMethods []string

	// AllowHeaders is a list of headers that can be used during the request.
	AllowHeaders []string
}

CORSConfig defines the configuration for CORS middleware.

type CheckFunc added in v1.1.0

type CheckFunc func() error

CheckFunc is a function that returns nil if healthy, or an error if unhealthy.

type Context

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

Context wraps http.ResponseWriter and *http.Request to provide convenient helper methods for HTTP handlers.

func (*Context) Bind

func (c *Context) Bind(v any) error

Bind decodes the request body into the provided struct v. It expects the request body to be JSON and handles closing the body. The struct v should be a pointer.

By default, unknown fields in the JSON are silently ignored. For stricter APIs that should reject unknown fields, use BindStrict instead.

func (*Context) BindStrict

func (c *Context) BindStrict(v any) error

BindStrict decodes the request body into the provided struct v, but returns an error if the JSON contains fields that are not present in the target struct. This is useful for security-sensitive APIs where you want to reject unexpected data.

Example error: "json: unknown field \"admin\""

func (*Context) Context

func (c *Context) Context() context.Context

Context returns the request's context.Context. This is crucial for passing to database drivers and other libraries that listen for cancellation signals.

func (*Context) Data

func (c *Context) Data(code int, contentType string, data []byte)

Data writes raw bytes to the response with the specified status code and content type.

Example:

c.Data(http.StatusOK, "image/png", pngBytes)

func (*Context) File

func (c *Context) File(filepath string)

File writes the specified file into the response body. It uses http.ServeFile which handles Content-Type detection, range requests, and Last-Modified headers automatically.

Example:

c.File("./reports/monthly.pdf")

func (*Context) FormValue

func (c *Context) FormValue(key string) string

FormValue returns the first value for the named component of the query. POST and PUT body parameters take precedence over URL query string values. This is useful for handling HTML form submissions (application/x-www-form-urlencoded).

func (*Context) Get

func (c *Context) Get(key string) (any, bool)

Get retrieves a value from the context's key-value store. Returns the value and a boolean indicating whether the key was found.

func (*Context) GetHeader

func (c *Context) GetHeader(key string) string

GetHeader returns the value of the specified request header.

func (*Context) Header

func (c *Context) Header() http.Header

Header returns the response header map.

func (*Context) JSON

func (c *Context) JSON(code int, v any) error

JSON writes a JSON response with the given status code. It sets the Content-Type header to "application/json; charset=utf-8" and encodes the provided value v to the response body.

Note: Headers and status code can only be written once. If you've already called Status(), Write(), or WriteString(), the headers set here will be ignored.

func (*Context) Method

func (c *Context) Method() string

Method returns the HTTP method of the request.

func (*Context) MustGet

func (c *Context) MustGet(key string) any

MustGet retrieves a value from the context's key-value store. It panics if the key is not found. Use this only when you are certain the key exists (e.g., set by middleware earlier in the chain).

func (*Context) Param

func (c *Context) Param(name string) string

Param returns the value of a path parameter from the request. This uses Go 1.22+ PathValue feature.

func (*Context) Path

func (c *Context) Path() string

Path returns the URL path of the request.

func (*Context) PostFormValue

func (c *Context) PostFormValue(key string) string

PostFormValue returns the first value for the named component of the POST, PATCH, or PUT request body. URL query parameters are ignored. Use this when you want to explicitly read only from the request body.

func (*Context) Query

func (c *Context) Query(key string) string

Query returns the value of a query string parameter. Query parameters are parsed once and cached for efficient repeated access.

func (*Context) QueryArray

func (c *Context) QueryArray(key string) []string

QueryArray returns all values for a query string parameter. This is useful for parameters that can have multiple values like ?tag=a&tag=b. Query parameters are parsed once and cached for efficient repeated access.

func (*Context) QueryDefault

func (c *Context) QueryDefault(key, defaultValue string) string

QueryDefault returns the value of a query string parameter, or the default value if the parameter is not present or empty. Query parameters are parsed once and cached for efficient repeated access.

func (*Context) Redirect

func (c *Context) Redirect(code int, url string)

Redirect sends an HTTP redirect to the specified URL. The code should be a redirect status code (3xx), typically:

  • http.StatusMovedPermanently (301) for permanent redirects
  • http.StatusFound (302) for temporary redirects
  • http.StatusSeeOther (303) for POST-to-GET redirects
  • http.StatusTemporaryRedirect (307) to preserve method
  • http.StatusPermanentRedirect (308) for permanent, method-preserving redirects

func (*Context) Request

func (c *Context) Request() *http.Request

Request returns the underlying *http.Request.

func (*Context) Set

func (c *Context) Set(key string, value any)

Set stores a value in the context's key-value store. The store is lazily initialized on first use to save memory.

func (*Context) SetContext

func (c *Context) SetContext(ctx context.Context)

SetContext updates the underlying request's context. Use this when middleware needs to set a timeout, deadline, or add tracing/telemetry data (e.g., OpenTelemetry spans) to the request.

Example:

ctx, cancel := context.WithTimeout(c.Context(), 5*time.Second)
defer cancel()
c.SetContext(ctx)

func (*Context) SetHeader

func (c *Context) SetHeader(key, value string)

SetHeader sets a response header with the given key and value.

func (*Context) Status

func (c *Context) Status(code int)

Status writes the HTTP status code to the response. This should be called before writing any body content.

func (*Context) Write

func (c *Context) Write(data []byte) (int, error)

Write writes data to the response body.

func (*Context) WriteString

func (c *Context) WriteString(s string) (int, error)

WriteString writes a string to the response body.

func (*Context) Writer

func (c *Context) Writer() http.ResponseWriter

Writer returns the underlying http.ResponseWriter.

func (*Context) Written

func (c *Context) Written() bool

Written returns true if the response has been written.

type ErrorHandler

type ErrorHandler func(*Context, error)

ErrorHandler is a function type for handling errors returned by handlers. It receives the Context and the error, allowing custom error responses.

type HandlerFunc

type HandlerFunc func(*Context) error

HandlerFunc is the custom handler signature for rig handlers. Unlike http.HandlerFunc, it accepts a *Context and returns an error, allowing handlers to return errors for centralized error handling.

type Health added in v1.1.0

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

Health manages liveness and readiness probes.

func NewHealth added in v1.1.0

func NewHealth() *Health

NewHealth creates a new Health manager.

func (*Health) AddLivenessCheck added in v1.1.0

func (h *Health) AddLivenessCheck(name string, check CheckFunc)

AddLivenessCheck adds a check that determines if the app is running (usually just a simple ping, or checking for deadlocks).

func (*Health) AddReadinessCheck added in v1.1.0

func (h *Health) AddReadinessCheck(name string, check CheckFunc)

AddReadinessCheck adds a check that must pass for the app to receive traffic (e.g., database connection, Redis, upstream API).

func (*Health) LiveHandler added in v1.1.0

func (h *Health) LiveHandler() HandlerFunc

LiveHandler returns a Rig HandlerFunc for liveness probes.

func (*Health) ReadyHandler added in v1.1.0

func (h *Health) ReadyHandler() HandlerFunc

ReadyHandler returns a Rig HandlerFunc for readiness probes.

type MiddlewareFunc

type MiddlewareFunc func(HandlerFunc) HandlerFunc

MiddlewareFunc is a function that wraps a HandlerFunc to provide additional functionality (logging, authentication, dependency injection, etc.). It follows the standard decorator pattern: it takes a handler and returns a new handler that wraps the original.

func CORS

func CORS(config CORSConfig) MiddlewareFunc

CORS creates middleware that sets the necessary headers for Cross-Origin requests.

Supports wildcard subdomains in AllowOrigins:

r.Use(rig.CORS(rig.CORSConfig{
    AllowOrigins: []string{
        "https://*.example.com",  // Matches any subdomain
        "https://api.other.com",  // Exact match
    },
    AllowMethods: []string{"GET", "POST"},
    AllowHeaders: []string{"Content-Type", "Authorization"},
}))

func DefaultCORS

func DefaultCORS() MiddlewareFunc

DefaultCORS creates CORS middleware with a permissive default configuration. It allows all origins and common HTTP methods and headers.

Example:

r := rig.New()
r.Use(rig.DefaultCORS())

func Recover

func Recover() MiddlewareFunc

Recover creates middleware that recovers from panics and returns a 500 error. This ensures the server never crashes from unhandled panics in handlers.

Example:

r := rig.New()
r.Use(rig.Recover())

type RouteGroup

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

RouteGroup represents a group of routes with a common prefix. Groups can have their own middleware that applies only to routes in the group.

func (*RouteGroup) DELETE

func (g *RouteGroup) DELETE(path string, handler HandlerFunc)

DELETE registers a handler for DELETE requests at the given path within the group. The path must be empty or begin with '/'. Panics if the path is invalid.

func (*RouteGroup) GET

func (g *RouteGroup) GET(path string, handler HandlerFunc)

GET registers a handler for GET requests at the given path within the group. The path must be empty or begin with '/'. Panics if the path is invalid.

func (*RouteGroup) Group

func (g *RouteGroup) Group(prefix string) *RouteGroup

Group creates a nested route group with an additional prefix. The nested group inherits the parent group's middleware. The prefix must begin with '/'. Panics if the prefix is invalid.

func (*RouteGroup) PATCH

func (g *RouteGroup) PATCH(path string, handler HandlerFunc)

PATCH registers a handler for PATCH requests at the given path within the group. The path must be empty or begin with '/'. Panics if the path is invalid.

func (*RouteGroup) POST

func (g *RouteGroup) POST(path string, handler HandlerFunc)

POST registers a handler for POST requests at the given path within the group. The path must be empty or begin with '/'. Panics if the path is invalid.

func (*RouteGroup) PUT

func (g *RouteGroup) PUT(path string, handler HandlerFunc)

PUT registers a handler for PUT requests at the given path within the group. The path must be empty or begin with '/'. Panics if the path is invalid.

func (*RouteGroup) Use

func (g *RouteGroup) Use(mw ...MiddlewareFunc)

Use appends one or more middleware to the group's middleware stack. These middleware only apply to routes registered on this group.

type Router

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

Router wraps http.ServeMux to provide a convenient API for routing HTTP requests with the custom HandlerFunc signature.

func New

func New() *Router

New creates a new Router with a fresh http.ServeMux.

func (*Router) DELETE

func (r *Router) DELETE(path string, handler HandlerFunc)

DELETE registers a handler for DELETE requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) GET

func (r *Router) GET(path string, handler HandlerFunc)

GET registers a handler for GET requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) Group

func (r *Router) Group(prefix string) *RouteGroup

Group creates a new route group with the given prefix. All routes registered on the group will have the prefix prepended. The prefix must begin with '/'. Panics if the prefix is invalid.

func (*Router) HEAD

func (r *Router) HEAD(path string, handler HandlerFunc)

HEAD registers a handler for HEAD requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) Handle

func (r *Router) Handle(pattern string, handler HandlerFunc)

Handle registers a handler for the given pattern with any HTTP method. The pattern follows Go 1.22+ ServeMux patterns (e.g., "GET /users/{id}"). The handler is wrapped with all registered middleware before being added.

func (*Router) Handler

func (r *Router) Handler() http.Handler

Handler returns the underlying http.ServeMux as an http.Handler.

func (*Router) OPTIONS

func (r *Router) OPTIONS(path string, handler HandlerFunc)

OPTIONS registers a handler for OPTIONS requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) PATCH

func (r *Router) PATCH(path string, handler HandlerFunc)

PATCH registers a handler for PATCH requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) POST

func (r *Router) POST(path string, handler HandlerFunc)

POST registers a handler for POST requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) PUT

func (r *Router) PUT(path string, handler HandlerFunc)

PUT registers a handler for PUT requests at the given path. The path must begin with '/'. Panics if the path is invalid.

func (*Router) Run

func (r *Router) Run(addr string) error

Run starts the HTTP server on the given address. This is a convenience method that wraps http.ListenAndServe.

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements the http.Handler interface. This allows the Router to be used directly with http.ListenAndServe.

func (*Router) SetErrorHandler

func (r *Router) SetErrorHandler(handler ErrorHandler)

SetErrorHandler sets a custom error handler for the router. This handler is called when a HandlerFunc returns an error.

func (*Router) Static

func (r *Router) Static(path, root string)

Static registers a route to serve static files from a directory. path is the URL path prefix (e.g., "/assets"). root is the local file system directory (e.g., "./public").

Example:

r.Static("/assets", "./public")
// GET /assets/css/style.css -> serves ./public/css/style.css

func (*Router) Use

func (r *Router) Use(mw ...MiddlewareFunc)

Use appends one or more middleware to the router's middleware stack. Middleware are executed in the order they are added.

Directories

Path Synopsis
Package auth provides authentication middleware for the rig HTTP library.
Package auth provides authentication middleware for the rig HTTP library.
Package logger provides HTTP request logging middleware for the rig framework.
Package logger provides HTTP request logging middleware for the rig framework.
render module
Package requestid provides middleware for generating and propagating request IDs.
Package requestid provides middleware for generating and propagating request IDs.
swagger module

Jump to

Keyboard shortcuts

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