anvil

package module
v0.0.0-...-a6eecc5 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2025 License: MIT Imports: 21 Imported by: 0

README

Anvil

An extra basic Go server toolkit built on top of Gorilla Mux, providing essential components for building robust HTTP servers and APIs.

Features

  • HTTP Server Management: Configurable HTTP server with graceful shutdown and timeout controls
  • Middleware Suite: Built-in logging, rate limiting, and CORS middleware
  • Error Handling: Standardized JSON error responses with automatic error handling
  • Security Tools: JWT authentication, Argon2 password hashing, and secure utilities
  • Utility Functions: UUID generation, date manipulation, and type-safe data extraction

Installation

go get github.com/arbenlabs/anvil

Quick Start

package main

import (
    "context"
    "net/http"
    
    "github.com/gorilla/mux"
    "arbenlabs/anvil"
)

func main() {
    // Create a new router
    router := mux.NewRouter()
    
    // Add middleware
    router.Use(anvil.LoggerMiddleware)
    router.Use(anvil.RateLimitWeb)
    
    // Define your handlers
    router.HandleFunc("/api/health", anvil.HandlerFunc(healthHandler))
    
    // Create and start server
    server := anvil.NewServer("8080").
        WithHandler(router).
        WithWriteTimeout(30 * time.Second)
    
    ctx := context.Background()
    server.Start(ctx)
}

func healthHandler(w http.ResponseWriter, r *http.Request) error {
    return anvil.RespondWithSuccess(w, http.StatusOK, map[string]string{
        "status": "healthy",
    })
}

Core Components

HTTP Server

The HTTPServer provides a configurable HTTP server with graceful shutdown capabilities.

// Create a new server with default settings
server := anvil.NewServer("8080")

// Configure timeouts
server := anvil.NewServer("8080").
    WithReadTimeout(15 * time.Second).
    WithWriteTimeout(30 * time.Second).
    WithIdleTimeout(120 * time.Second)

// Start the server with graceful shutdown
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
server.Start(ctx)
Error Handling

Standardized error handling with automatic JSON response formatting.

// Define handlers that return errors
func createUserHandler(w http.ResponseWriter, r *http.Request) error {
    // Your logic here
    if err := validateUser(r); err != nil {
        return err // Automatically converted to JSON error response
    }
    
    return anvil.RespondWithSuccess(w, http.StatusCreated, user)
}

// Wrap handlers with error handling
http.HandleFunc("/api/users", anvil.HandlerFunc(createUserHandler))
Middleware
Logging Middleware

Automatically logs request information including IP address, user agent, and request details.

router.Use(anvil.LoggerMiddleware)
Rate Limiting

Multiple rate limiting configurations for different use cases:

// Public API rate limiting (5000 req/sec, burst 100)
router.Use(anvil.RateLimitPublic)

// Internal API rate limiting (10000 req/sec, burst 200)
router.Use(anvil.RateLimitInternal)

// Web API rate limiting (300 req/sec, burst 30)
router.Use(anvil.RateLimitWeb)

// Strict rate limiting (100 req/sec, burst 10)
router.Use(anvil.RateLimitStrict)
CORS

Configure CORS for cross-origin requests:

corsConfig := anvil.CORS(
    []string{"https://yourdomain.com"},
    []string{"GET", "POST", "PUT", "DELETE"},
    true,
)

handler := anvil.PopulateHandlerWithCORS(corsConfig, router)
Security Tools
JWT Authentication
anvtools import "arbenlabs/anvil/tools"

// Create JWT service
jwtService := anvtools.NewJsonWebToken("your-app.com", []byte("your-secret-key"))

// Generate token
claims := anvtools.JWTClaims{
    ID:    "user123",
    Email: "user@example.com",
}
token, err := jwtService.Generate(claims, nil) // 15 min default
token, err := jwtService.Generate(claims, &30) // 30 min custom

// Verify token
claims, err := jwtService.Verify(tokenString)
Password Hashing

Secure password hashing using Argon2id:

anvtools import "arbenlabs/anvil/tools"

// Hash password
hash, err := anvtools.GenerateHashString("myPassword123")

// Verify password
match, err := anvtools.IsMatchingInputAndHash("myPassword123", storedHash)
Utility Functions
UUID Generation
anvtools import "arbenlabs/anvil/tools"

// Generate standard UUID
id := anvtools.GenerateUUID()

// Generate namespaced UUID
userID := anvtools.GenerateNamespaceUUID("user")
orderID := anvtools.GenerateNamespaceUUID("order")
Date Utilities
anvtools import "arbenlabs/anvil/tools"

// Get current date at midnight UTC
today := anvtools.GetCurrentDate()

// Calculate future date
futureDate := anvtools.GetFutureDate(1, 6, 15) // 1 year, 6 months, 15 days
Type-Safe Data Extraction
anvtools import "arbenlabs/anvil/tools"

data := map[string]interface{}{
    "name": "John",
    "age":  30,
    "email": nil,
}

// Safe type extraction
name := anvtools.SafeString(data, "name")     // "John"
email := anvtools.SafeString(data, "email")   // ""
age := anvtools.SafeInt(data, "age")          // 30

API Reference

HTTPServer
  • NewServer(address string) *HTTPServer - Create new server with defaults
  • WithReadTimeout(duration) *HTTPServer - Set read timeout
  • WithWriteTimeout(duration) *HTTPServer - Set write timeout
  • WithIdleTimeout(duration) *HTTPServer - Set idle timeout
  • WithHandler(handler) *HTTPServer - Set HTTP handler
  • Start(ctx context.Context) - Start server with graceful shutdown
Error Handling
  • HandlerFunc(APIFunc) http.HandlerFunc - Wrap handler with error handling
  • RespondWithError(w, err) error - Send JSON error response
  • RespondWithSuccess(w, status, data) error - Send JSON success response
Middleware
  • LoggerMiddleware(next) http.Handler - Request logging
  • RateLimitPublic(next) http.Handler - Public API rate limiting
  • RateLimitInternal(next) http.Handler - Internal API rate limiting
  • RateLimitWeb(next) http.Handler - Web API rate limiting
  • RateLimitStrict(next) http.Handler - Strict rate limiting
  • CORS(origins, methods, credentials) *cors.Cors - CORS configuration
Tools Package
JWT
  • NewJsonWebToken(issuer, key) *JWT - Create JWT service
  • Generate(claims, expiration) (string, error) - Generate token
  • Verify(token) (JWTClaims, error) - Verify token
Hashing
  • GenerateHashString(input) (string, error) - Hash password
  • IsMatchingInputAndHash(input, hash) (bool, error) - Verify password
Utilities
  • GenerateUUID() string - Generate UUID
  • GenerateNamespaceUUID(namespace) string - Generate namespaced UUID
  • GetCurrentDate() time.Time - Get current date
  • GetFutureDate(years, months, days) time.Time - Calculate future date
  • SafeString(data, key) string - Safe string extraction
  • SafeInt(data, key) int - Safe int extraction
  • SafeBool(data, key) bool - Safe bool extraction
  • SafeTime(data, key) time.Time - Safe time extraction

Configuration

Default Timeouts
  • Read Timeout: 15 seconds
  • Write Timeout: 30 seconds
  • Idle Timeout: 120 seconds
  • Graceful Shutdown: 30 seconds
Rate Limiting Configurations
  • Public API: 5000 req/sec, burst 100
  • Internal API: 10000 req/sec, burst 200
  • Web API: 300 req/sec, burst 30
  • Strict API: 100 req/sec, burst 10

Dependencies

  • github.com/gorilla/mux - HTTP router
  • github.com/golang-jwt/jwt/v5 - JWT handling
  • github.com/rs/cors - CORS middleware
  • github.com/rs/zerolog - Structured logging
  • golang.org/x/crypto - Argon2 hashing
  • golang.org/x/time - Rate limiting
  • github.com/google/uuid - UUID generation

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

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

Documentation

Index

Constants

View Source
const (
	// DefaultShutdownGracePeriod is the default duration for graceful server shutdown.
	// This allows existing connections to finish before the server terminates.
	DefaultShutdownGracePeriod = time.Second * 30

	// DefaultWriteTimeout is the default maximum duration for writing the entire request.
	// This prevents slow clients from consuming server resources indefinitely.
	DefaultWriteTimeout = time.Second * 30

	// DefaultReadTimeout is the default maximum duration for reading the entire request.
	// This prevents slow clients from consuming server resources indefinitely.
	DefaultReadTimeout = time.Second * 15

	// DefaultIdleTimeout is the default maximum amount of time to wait for the next request.
	// This helps manage connection pooling and resource utilization.
	DefaultIdleTimeout = time.Second * 120
)

Variables

This section is empty.

Functions

func CORS

func CORS(origins []string, methods []string, allowCredentials bool) *cors.Cors

CORS creates a new CORS middleware with the specified configuration. This function creates a CORS handler that can be used to handle Cross-Origin Resource Sharing requests. It configures which origins, methods, and credentials are allowed for cross-origin requests.

Example usage:

corsHandler := CORS([]string{"https://example.com"}, []string{"GET", "POST"}, true)
handler := PopulateHandlerWithCORS(corsHandler, myHandler)

Parameters:

  • origins: List of allowed origin URLs (e.g., ["https://example.com"])
  • methods: List of allowed HTTP methods (e.g., ["GET", "POST", "PUT"])
  • allowCredentials: Whether to allow credentials in cross-origin requests

Returns:

  • *cors.Cors: A configured CORS middleware handler

func ClerkAuthMiddleware

func ClerkAuthMiddleware(clerk clerk.Client) func(next http.Handler) http.Handler

func ClerkWebhookMiddleware

func ClerkWebhookMiddleware(clerk clerk.Client, secret string) func(next http.Handler) http.Handler

func GenerateHashString

func GenerateHashString(input string) (string, error)

GenerateHashString creates a secure hash of the input string using Argon2id. This function uses the Argon2id variant, which is recommended for password hashing due to its resistance to both GPU-based attacks and side-channel attacks.

The function generates a cryptographically secure random salt and applies the Argon2id algorithm with the following parameters:

  • Memory: 64 MiB (64 * 1024 KiB)
  • Iterations: 3
  • Parallelism: 2 threads
  • Salt length: 16 bytes
  • Key length: 32 bytes

The returned hash string follows the standard Argon2 format:

$argon2id$v=19$m=65536,t=3,p=2$[salt]$[hash]

Example usage:

hash, err := GenerateHashString("myPassword123")
if err != nil {
    // handle error
}
// Store hash in database

Parameters:

  • input: The string to hash (typically a password)

Returns:

  • string: The encoded hash string in Argon2 format
  • error: Any error that occurred during hashing (e.g., crypto/rand failure)

func GenerateNamespaceUUID

func GenerateNamespaceUUID(namespace string) string

GenerateNamespaceUUID creates a UUID with a namespace suffix. This function generates a standard UUID and appends the provided namespace to create a namespaced identifier. This is useful for creating unique identifiers that are scoped to a specific context or domain.

The generated UUID follows the standard UUID v4 format, and the namespace is appended with a hyphen separator. This creates identifiers that are both globally unique and contextually meaningful.

Example usage:

userID := GenerateNamespaceUUID("user")
// Result: "550e8400-e29b-41d4-a716-446655440000-user"

orderID := GenerateNamespaceUUID("order")
// Result: "550e8400-e29b-41d4-a716-446655440000-order"

Parameters:

  • namespace: The namespace to append to the UUID

Returns:

  • string: A namespaced UUID string

func GenerateUUID

func GenerateUUID() string

GenerateUUID creates a new random UUID (Universally Unique Identifier). This function generates a version 4 UUID using the crypto/rand package, ensuring cryptographic randomness and uniqueness. UUIDs are useful for creating globally unique identifiers for database records, API endpoints, and other resources that need to be uniquely identified.

The generated UUID follows the standard format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where x is a hexadecimal digit and y is one of 8, 9, A, or B.

Example usage:

id := GenerateUUID()
// Result: "550e8400-e29b-41d4-a716-446655440000"

Returns:

  • string: A new random UUID string

func GetCurrentDate

func GetCurrentDate() time.Time

GetCurrentDate returns the current date at midnight UTC. This function returns a time.Time value representing the current date with the time set to 00:00:00 UTC. This is useful for date-based operations where you need to work with dates without time components, such as date ranges, daily statistics, or date-based filtering.

The function extracts the year, month, and day from the current time and creates a new time.Time value with those components and zero time.

Example usage:

today := GetCurrentDate()
// Result: 2024-01-15 00:00:00 +0000 UTC

Returns:

  • time.Time: The current date at midnight UTC

func GetFutureDate

func GetFutureDate(years int, months int, days int) time.Time

GetFutureDate calculates a future date based on the specified offsets. This function adds the specified number of years, months, and days to the current date and returns the resulting future date. This is useful for calculating expiration dates, subscription end dates, or other future time-based events.

The function uses time.AddDate which properly handles month and year boundaries, including leap years and varying month lengths.

Example usage:

// Get date 1 year, 6 months, and 15 days from now
futureDate := GetFutureDate(1, 6, 15)
// Result: Current date + 1 year + 6 months + 15 days

// Get date 2 years from now
twoYearsFromNow := GetFutureDate(2, 0, 0)

Parameters:

  • years: Number of years to add (can be negative for past dates)
  • months: Number of months to add (can be negative)
  • days: Number of days to add (can be negative)

Returns:

  • time.Time: The calculated future date

func HandlerFunc

func HandlerFunc(f APIFunc) http.HandlerFunc

HandlerFunc converts an APIFunc to a standard http.HandlerFunc with automatic error handling. This function wraps API handlers to provide consistent error response formatting. When the wrapped function returns an error, it automatically calls RespondWithError to send a properly formatted JSON error response to the client.

Example usage:

http.HandleFunc("/api/users", HandlerFunc(createUserHandler))

Parameters:

  • f: The APIFunc to wrap with error handling

Returns:

  • http.HandlerFunc: A standard HTTP handler function with error handling

func IsMatchingInputAndHash

func IsMatchingInputAndHash(input, encodedHash string) (match bool, err error)

IsMatchingInputAndHash verifies if an input string matches a previously generated hash. This function safely compares the input string against a stored hash using constant-time comparison to prevent timing attacks.

The function:

  1. Decodes the stored hash to extract parameters, salt, and hash
  2. Generates a new hash using the same parameters and salt
  3. Compares the hashes using constant-time comparison

This function is typically used for password verification during login.

Example usage:

match, err := IsMatchingInputAndHash("myPassword123", storedHash)
if err != nil {
    // handle error (invalid hash format, incompatible version, etc.)
}
if match {
    // password is correct
} else {
    // password is incorrect
}

Parameters:

  • input: The string to verify (typically a password)
  • encodedHash: The previously generated hash string to compare against

Returns:

  • bool: true if the input matches the hash, false otherwise
  • error: Any error that occurred during verification (e.g., invalid hash format)

func LoggerMiddleware

func LoggerMiddleware(next http.Handler) http.Handler

LoggerMiddleware creates an HTTP middleware that logs request information. This middleware extracts and logs the client's IP address, host, server address, user agent, and request details (method, path, remote address) for each HTTP request. The logging is done using the structured logging package (slog) for better log parsing.

The middleware logs the following information:

  • IP address of the client
  • Host from the request URL
  • Server address
  • User agent string
  • Request method, path, and remote address

Example usage:

http.Handle("/api", LoggerMiddleware(myHandler))

Parameters:

  • next: The next HTTP handler in the middleware chain

Returns:

  • http.Handler: A new handler that logs requests before passing them to the next handler

func PopulateHandlerWithCORS

func PopulateHandlerWithCORS(crossOrigin *cors.Cors, handler http.Handler) http.Handler

PopulateHandlerWithCORS wraps an HTTP handler with CORS middleware. This function applies CORS configuration to an existing HTTP handler, enabling cross-origin requests according to the specified CORS settings.

The CORS middleware will be applied to all requests handled by the provided handler, adding the necessary CORS headers to responses based on the CORS configuration.

Example usage:

corsHandler := CORS([]string{"https://example.com"}, []string{"GET", "POST"}, true)
finalHandler := PopulateHandlerWithCORS(corsHandler, myHandler)
http.Handle("/api", finalHandler)

Parameters:

  • crossOrigin: The CORS configuration to apply
  • handler: The HTTP handler to wrap with CORS middleware

Returns:

  • http.Handler: A new handler with CORS middleware applied

func RateLimitInternal

func RateLimitInternal(next http.Handler) http.Handler

RateLimitInternal creates middleware that applies internal API rate limiting. This middleware uses the RateLimitInternalAPI configuration, which allows 10000 requests per second with a burst capacity of 200 requests. It's suitable for internal service-to-service communication.

The middleware tracks clients by IP address and applies rate limiting per client. When a client exceeds the rate limit, it receives a 429 (Too Many Requests) response with a JSON error message.

Example usage:

http.Handle("/api/internal", RateLimitInternal(myHandler))

Parameters:

  • next: The next HTTP handler in the middleware chain

Returns:

  • http.Handler: A new handler that applies internal API rate limiting

func RateLimitPublic

func RateLimitPublic(next http.Handler) http.Handler

RateLimitPublic creates middleware that applies public API rate limiting. This middleware uses the RateLimitPublicAPI configuration, which allows 5000 requests per second with a burst capacity of 100 requests. It's suitable for public-facing endpoints that need to handle high traffic.

The middleware tracks clients by IP address and applies rate limiting per client. When a client exceeds the rate limit, it receives a 429 (Too Many Requests) response with a JSON error message.

Example usage:

http.Handle("/api/public", RateLimitPublic(myHandler))

Parameters:

  • next: The next HTTP handler in the middleware chain

Returns:

  • http.Handler: A new handler that applies public API rate limiting

func RateLimitStrict

func RateLimitStrict(next http.Handler) http.Handler

RateLimitStrict creates middleware that applies strict API rate limiting. This middleware uses the RateLimitStrictAPI configuration, which allows 100 requests per second with a burst capacity of 10 requests. It's suitable for sensitive endpoints like authentication or payment processing.

The middleware tracks clients by IP address and applies rate limiting per client. When a client exceeds the rate limit, it receives a 429 (Too Many Requests) response with a JSON error message.

Example usage:

http.Handle("/api/auth", RateLimitStrict(myHandler))

Parameters:

  • next: The next HTTP handler in the middleware chain

Returns:

  • http.Handler: A new handler that applies strict API rate limiting

func RateLimitWeb

func RateLimitWeb(next http.Handler) http.Handler

RateLimitWeb creates middleware that applies user web API rate limiting. This middleware uses the RateLimitUserWebAPI configuration, which allows 300 requests per second with a burst capacity of 30 requests. It's suitable for web applications where users interact directly with the API.

The middleware tracks clients by IP address and applies rate limiting per client. When a client exceeds the rate limit, it receives a 429 (Too Many Requests) response with a JSON error message.

Example usage:

http.Handle("/api/web", RateLimitWeb(myHandler))

Parameters:

  • next: The next HTTP handler in the middleware chain

Returns:

  • http.Handler: A new handler that applies user web API rate limiting

func RespondWithError

func RespondWithError(w http.ResponseWriter, e error) error

RespondWithError sends a JSON error response to the client. This function formats the error message and includes a timestamp in the response. It automatically sets the HTTP status code to 400 (Bad Request) and the Content-Type header to application/json.

The error response follows this structure:

{
  "error": "error message here",
  "timestamp": "2024-01-01 12:00:00 +0000 UTC"
}

Parameters:

  • w: The HTTP response writer
  • e: The error to format and send

Returns:

  • error: Any error that occurred during response writing

func RespondWithSuccess

func RespondWithSuccess(w http.ResponseWriter, status int, v any) error

RespondWithSuccess sends a JSON success response to the client. This function sends the provided data as JSON with the specified HTTP status code. It automatically sets the Content-Type header to application/json.

Parameters:

  • w: The HTTP response writer
  • status: The HTTP status code to return (e.g., 200, 201, 204)
  • v: The data to encode as JSON in the response body

Returns:

  • error: Any error that occurred during JSON encoding or writing

func SafeBool

func SafeBool(data map[string]interface{}, key string) bool

SafeBool safely extracts a boolean value from a map[string]interface{}. This function provides type-safe access to boolean values in maps that contain mixed types (interface{}). It handles cases where the key doesn't exist, the value is nil, or the value is not a boolean type.

The function returns false if:

  • The key doesn't exist in the map
  • The value is nil
  • The value is not a boolean type

This is useful when working with JSON data, database results, or any map that contains mixed data types and you need to safely extract boolean values without causing panics.

Example usage:

data := map[string]interface{}{
    "active": true,
    "verified": false,
    "email": nil,
    "name": "John",
}
active := SafeBool(data, "active")     // Returns: true
verified := SafeBool(data, "verified") // Returns: false
email := SafeBool(data, "email")       // Returns: false
missing := SafeBool(data, "missing")   // Returns: false

Parameters:

  • data: The map containing mixed data types
  • key: The key to look up in the map

Returns:

  • bool: The boolean value if found and valid, false otherwise

func SafeString

func SafeString(data map[string]interface{}, key string) string

SafeString safely extracts a string value from a map[string]interface{}. This function provides type-safe access to string values in maps that contain mixed types (interface{}). It handles cases where the key doesn't exist, the value is nil, or the value is not a string type.

The function returns an empty string if:

  • The key doesn't exist in the map
  • The value is nil
  • The value is not a string type

This is useful when working with JSON data, database results, or any map that contains mixed data types and you need to safely extract string values without causing panics.

Example usage:

data := map[string]interface{}{
    "name": "John",
    "age":  30,
    "email": nil,
}
name := SafeString(data, "name")     // Returns: "John"
email := SafeString(data, "email")   // Returns: ""
missing := SafeString(data, "missing") // Returns: ""

Parameters:

  • data: The map containing mixed data types
  • key: The key to look up in the map

Returns:

  • string: The string value if found and valid, empty string otherwise

func SafeTime

func SafeTime(data map[string]interface{}, key string) time.Time

SafeTime safely extracts a time.Time value from a map[string]interface{}. This function provides type-safe access to time.Time values in maps that contain mixed types (interface{}). It handles cases where the key doesn't exist, the value is nil, or the value is not a time.Time type.

The function returns the zero value of time.Time if:

  • The key doesn't exist in the map
  • The value is nil
  • The value is not a time.Time type

This is useful when working with JSON data, database results, or any map that contains mixed data types and you need to safely extract time values without causing panics.

Example usage:

data := map[string]interface{}{
    "created_at": time.Now(),
    "updated_at": nil,
    "name": "John",
}
createdAt := SafeTime(data, "created_at") // Returns: actual time
updatedAt := SafeTime(data, "updated_at") // Returns: zero time
missing := SafeTime(data, "missing")      // Returns: zero time

Parameters:

  • data: The map containing mixed data types
  • key: The key to look up in the map

Returns:

  • time.Time: The time.Time value if found and valid, zero time otherwise

Types

type APIFunc

type APIFunc func(http.ResponseWriter, *http.Request) error

APIFunc represents a function signature for HTTP handlers that return errors. This type is used to standardize error handling across all API endpoints. Functions implementing this signature should handle the HTTP request and return an error if something goes wrong, which will be automatically converted to a JSON error response.

type AllowedMethods

type AllowedMethods string

AllowedMethods represents HTTP methods that are allowed in CORS configuration. This type provides type safety when specifying allowed HTTP methods.

const (
	// AllowedMethodsGet represents the HTTP GET method for CORS configuration.
	AllowedMethodsGet AllowedMethods = "GET"

	// AllowedMethodsPost represents the HTTP POST method for CORS configuration.
	AllowedMethodsPost AllowedMethods = "POST"

	// AllowedMethodsPatch represents the HTTP PATCH method for CORS configuration.
	AllowedMethodsPatch AllowedMethods = "PATCH"

	// AllowedMethodsPut represents the HTTP PUT method for CORS configuration.
	AllowedMethodsPut AllowedMethods = "PUT"

	// AllowedMethodsDelete represents the HTTP DELETE method for CORS configuration.
	AllowedMethodsDelete AllowedMethods = "DELETE"
)

type HTTPServer

type HTTPServer struct {
	Address      string        // The server address (e.g., ":8080")
	WriteTimeout time.Duration // Maximum duration for writing the entire request
	ReadTimeout  time.Duration // Maximum duration for reading the entire request
	IdleTimeout  time.Duration // Maximum amount of time to wait for the next request
	Handler      http.Handler  // The HTTP handler to serve requests
}

HTTPServer represents a configurable HTTP server with timeout settings. This struct provides a builder pattern for creating HTTP servers with customizable timeout configurations and graceful shutdown capabilities.

func NewServer

func NewServer(address string) *HTTPServer

NewServer creates a new HTTPServer instance with default timeout settings. This function initializes a server with sensible defaults for production use. The address parameter should be just the port number (e.g., "8080"), and it will be automatically formatted as ":port".

Example usage:

server := NewServer("8080")
server.Start(context.Background(), "8080")

Parameters:

  • address: The port number for the server (e.g., "8080")

Returns:

  • *HTTPServer: A new HTTPServer instance with default settings

func (*HTTPServer) Start

func (h *HTTPServer) Start(ctx context.Context)

Start begins listening for HTTP requests and handles graceful shutdown. This method starts the HTTP server on the configured address and sets up graceful shutdown handling. The server will listen for shutdown signals through the provided context and gracefully terminate when the context is cancelled.

The server runs in a goroutine and the method blocks until the context is cancelled. When shutdown is initiated, the server waits for existing connections to finish before terminating, with a configurable grace period.

Example usage:

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
server.Start(ctx)

Parameters:

  • ctx: Context for controlling server lifecycle and shutdown

func (*HTTPServer) WithHandler

func (h *HTTPServer) WithHandler(handler http.Handler) *HTTPServer

WithHandler sets the HTTP handler for the server. This method returns a new HTTPServer instance with the specified handler, following the builder pattern for configuration.

The handler is responsible for processing HTTP requests and generating responses. This can be a router, middleware chain, or any http.Handler implementation.

Parameters:

  • handler: The HTTP handler to use for processing requests

Returns:

  • *HTTPServer: A new HTTPServer instance with the updated handler

func (*HTTPServer) WithIdleTimeout

func (h *HTTPServer) WithIdleTimeout(ito time.Duration) *HTTPServer

WithIdleTimeout sets the idle timeout for the HTTP server. This method returns a new HTTPServer instance with the specified idle timeout, following the builder pattern for configuration.

The idle timeout is the maximum amount of time to wait for the next request when keep-alives are enabled. This helps manage connection pooling.

Parameters:

  • ito: The idle timeout duration

Returns:

  • *HTTPServer: A new HTTPServer instance with the updated idle timeout

func (*HTTPServer) WithReadTimeout

func (h *HTTPServer) WithReadTimeout(rto time.Duration) *HTTPServer

WithReadTimeout sets the read timeout for the HTTP server. This method returns a new HTTPServer instance with the specified read timeout, following the builder pattern for configuration.

The read timeout is the maximum duration for reading the entire request, including the body. This helps prevent slow clients from consuming server resources.

Parameters:

  • rto: The read timeout duration

Returns:

  • *HTTPServer: A new HTTPServer instance with the updated read timeout

func (*HTTPServer) WithWriteTimeout

func (h *HTTPServer) WithWriteTimeout(wto time.Duration) *HTTPServer

WithWriteTimeout sets the write timeout for the HTTP server. This method returns a new HTTPServer instance with the specified write timeout, following the builder pattern for configuration.

The write timeout is the maximum duration for writing the entire request, including the body. This helps prevent slow clients from consuming server resources.

Parameters:

  • wto: The write timeout duration

Returns:

  • *HTTPServer: A new HTTPServer instance with the updated write timeout

type JWT

type JWT struct {
	Issuer     string `json:"issuer"`      // The issuer of the JWT (typically your service domain)
	SigningKey []byte `json:"signing_key"` // The secret key used to sign and verify tokens
}

JWT represents a JSON Web Token service with configuration for token generation and verification. This struct encapsulates the issuer information and signing key needed for JWT operations. The issuer is typically the domain or service name that creates the token, and the signing key is used to sign and verify the token's authenticity.

func NewJsonWebToken

func NewJsonWebToken(issuer string, key []byte) *JWT

NewJsonWebToken creates a new JWT service instance with the specified issuer and signing key. This function initializes a JWT service that can be used to generate and verify tokens. The issuer should be a unique identifier for your service (e.g., "myapp.com"), and the signing key should be a secure, randomly generated secret.

Example usage:

jwtService := NewJsonWebToken("myapp.com", []byte("your-secret-key"))
token, err := jwtService.Generate(JWTClaims{ID: "123", Email: "user@example.com"}, nil)

Parameters:

  • issuer: The issuer identifier for the JWT (typically your service domain)
  • key: The secret key used to sign and verify tokens (should be at least 32 bytes)

Returns:

  • *JWT: A new JWT service instance

func (*JWT) Generate

func (tkn *JWT) Generate(claims JWTClaims, expiration *int) (string, error)

Generate creates a new JSON Web Token with the specified claims and expiration. This function creates a JWT using the HS256 signing algorithm with the configured issuer and signing key. The token includes standard JWT claims (exp, iat, nbf, iss, sub, jti) along with the custom user claims.

The expiration parameter is optional:

  • If nil, the token expires in 15 minutes
  • If >= 0, the token expires in the specified number of minutes

The generated token includes the following claims:

  • exp: Expiration time
  • iat: Issued at time
  • nbf: Not before time
  • iss: Issuer (from JWT configuration)
  • sub: Subject (user's email)
  • jti: JWT ID (user's ID)

Example usage:

claims := JWTClaims{ID: "user123", Email: "user@example.com"}
token, err := jwtService.Generate(claims, nil) // 15 minute expiration
token, err := jwtService.Generate(claims, &30) // 30 minute expiration

Parameters:

  • claims: The user-specific claims to include in the token
  • expiration: Optional expiration time in minutes (nil for 15 minutes default)

Returns:

  • string: The signed JWT string
  • error: Any error that occurred during token generation

func (*JWT) Verify

func (tkn *JWT) Verify(tokenString string) (JWTClaims, error)

Verify validates a JSON Web Token and extracts the user claims. This function verifies the token's signature using the configured signing key and extracts the user claims if the token is valid. It checks for:

  • Valid signature using HS256 algorithm
  • Token expiration
  • Token not-before time
  • Issuer validation

The function returns the user claims (ID and email) if the token is valid, or an error if the token is invalid, expired, or malformed.

Example usage:

claims, err := jwtService.Verify(tokenString)
if err != nil {
    // Token is invalid, expired, or malformed
}
// Use claims.ID and claims.Email

Parameters:

  • tokenString: The JWT string to verify

Returns:

  • JWTClaims: The user claims extracted from the token (ID and email)
  • error: Any error that occurred during verification (invalid signature, expired, etc.)

type JWTClaims

type JWTClaims struct {
	ID    string `json:"user_id"` // The unique identifier of the user
	Email string `json:"email"`   // The email address of the user
}

JWTClaims represents the custom claims structure for JSON Web Tokens. This struct defines the user-specific data that will be embedded in the JWT. The claims are included in the token payload and can be extracted during verification.

type Message

type Message struct {
	Status    string    `json:"status"`    // The status of the request (e.g., "Request Failed")
	Body      string    `json:"body"`      // The error message body
	Locked    bool      `json:"locked"`    // Whether the request is locked due to rate limiting
	Timestamp time.Time `json:"timestamp"` // When the rate limit was triggered
}

Message represents a standardized error response structure for rate limiting. This struct is used to provide consistent error messages when rate limits are exceeded. It includes status information, a descriptive message, a locked flag, and a timestamp for debugging and monitoring purposes.

type RateLimit

type RateLimit *rate.Limiter

RateLimit is a type alias for rate.Limiter to provide semantic meaning. This type represents a rate limiter that controls the frequency of requests based on the configured rate and burst limits.

var (
	// RateLimitPublicAPI provides rate limiting for public API endpoints.
	// This limiter allows 5000 requests per second with a burst capacity of 100 requests.
	// Suitable for public-facing APIs that need to handle high traffic while preventing abuse.
	RateLimitPublicAPI RateLimit = rate.NewLimiter(5000, 100)

	// RateLimitInternalAPI provides rate limiting for internal API endpoints.
	// This limiter allows 10000 requests per second with a burst capacity of 200 requests.
	// Suitable for internal services that need higher throughput than public APIs.
	RateLimitInternalAPI RateLimit = rate.NewLimiter(10000, 200)

	// RateLimitUserWebAPI provides rate limiting for user-facing web APIs.
	// This limiter allows 300 requests per second with a burst capacity of 30 requests.
	// Suitable for web applications where users interact directly with the API.
	RateLimitUserWebAPI RateLimit = rate.NewLimiter(300, 30)

	// RateLimitStrictAPI provides strict rate limiting for sensitive endpoints.
	// This limiter allows 100 requests per second with a burst capacity of 10 requests.
	// Suitable for authentication endpoints, payment processing, or other sensitive operations.
	RateLimitStrictAPI RateLimit = rate.NewLimiter(100, 10)
)

Jump to

Keyboard shortcuts

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