simplehttp

package module
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Dec 16, 2025 License: MIT Imports: 17 Imported by: 1

README

SimpleHttp

SimpleHttp is a flexible HTTP handler interface in Go that provides a unified abstraction layer for multiple web frameworks. It allows you to write your web applications once and switch between different underlying frameworks (Echo, Fiber, etc.) without changing your application code.

Features

  • Framework Agnostic: Supports multiple frameworks (Echo, Fiber, FastHTTP, Gin) through a consistent interface
  • Modular Middleware: Built-in support for logging, authentication, rate limiting, CORS, and more
  • Standardized Header Parsing: Easily extract auth tokens, API keys, IP addresses, and browser info
  • Websocket Support: Integrated WebSocket handling with the same consistent API
  • File Handling: Upload and download files with size limits and content validation
  • Configuration via Environment: Seamlessly switch between frameworks using environment variables
  • Graceful Shutdown: Handle shutdowns gracefully for better user experience

Installation

go get github.com/medatechnology/simplehttp

Quick Start

1. Set Up Your Project

Create a new Go project and add SimpleHttp as a dependency:

mkdir myapi
cd myapi
go mod init github.com/yourusername/myapi
go get github.com/medatechnology/simplehttp

Create a .env file in your project root:

# Framework to use (echo, fiber, etc.)
SIMPLEHTTP_FRAMEWORK=echo

# Application settings
SIMPLEHTTP_APP_NAME=MyAPIService
SIMPLEHTTP_PORT=8080
SIMPLEHTTP_HOST_NAME=localhost

# Timeouts in seconds
SIMPLEHTTP_READ_TIMEOUT=30
SIMPLEHTTP_WRITE_TIMEOUT=30
SIMPLEHTTP_IDLE_TIMEOUT=60

# Debug mode
SIMPLEHTTP_DEBUG=false

# Display startup message
SIMPLEHTTP_FRAMEWORK_STARTUP_MESSAGE=true
2. Create Your First API

Create a main.go file:

package main

import (
    "log"
    "net/http"
    "os"
    "os/signal"
    "context"
    "time"

    "github.com/medatechnology/simplehttp"
    "github.com/medatechnology/simplehttp/framework/echo" // Or fiber
)

func main() {
    // Load configuration from .env
    config := simplehttp.LoadConfig()

    // Create server instance
    server := echo.NewServer(config)

    // Add middleware
    server.Use(
        simplehttp.MiddlewareRequestID(),
        simplehttp.MiddlewareLogger(simplehttp.NewDefaultLogger()),
    )

    // Define routes
    server.GET("/hello", func(c simplehttp.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })

    api := server.Group("/api")
    {
        api.GET("/status", func(c simplehttp.Context) error {
            return c.JSON(http.StatusOK, map[string]string{
                "status": "running",
                "version": "1.0.0",
            })
        })
    }

    // Start server in a goroutine
    go func() {
        if err := server.Start(""); err != nil {
            log.Printf("Server error: %v", err)
        }
    }()

    // Wait for interrupt signal
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt)
    <-quit

    // Gracefully shutdown
    log.Println("Shutting down server...")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    if err := server.Shutdown(ctx); err != nil {
        log.Fatal("Server forced to shutdown:", err)
    }

    log.Println("Server exiting")
}
3. Run Your API

Build and run your application:

go build
./myapi

Your API is now running! Try these endpoints:

Middleware

SimpleHttp comes with several built-in middleware components that you can use to enhance your application:

RequestID Middleware

Adds a unique identifier to each request:

server.Use(simplehttp.MiddlewareRequestID())
Logger Middleware

Logs incoming requests and outgoing responses:

// Use default logger
server.Use(simplehttp.MiddlewareLogger(simplehttp.NewDefaultLogger()))

// Use custom logger with configuration
logConfig := &simplehttp.DefaultLoggerConfig{
    Level:      simplehttp.LogLevelDebug,
    TimeFormat: "2006/01/02 15:04:05",
    Output:     os.Stdout,
    Prefix:     "[MyAPI] ",
}
logger := simplehttp.NewDefaultLogger(logConfig)
server.Use(simplehttp.MiddlewareLogger(logger))
Timeout Middleware

Sets a maximum duration for request handling:

timeoutConfig := simplehttp.TimeOutConfig{
    ReadTimeout:  30 * time.Second,
    WriteTimeout: 30 * time.Second,
    IdleTimeout:  60 * time.Second,
}
server.Use(simplehttp.MiddlewareTimeout(timeoutConfig))
HeaderParser Middleware

Parses common HTTP headers into a structured object:

server.Use(simplehttp.MiddlewareHeaderParser())

// Later in your handler
func myHandler(c simplehttp.Context) error {
    headers := c.GetHeaders()
    
    // Access parsed header data
    userAgent := headers.UserAgent
    browserName := headers.Browser
    clientIP := headers.RealIP
    requestID := headers.RequestID
    
    return c.JSON(http.StatusOK, map[string]string{
        "browser": browserName,
        "ip": clientIP,
    })
}
CORS Middleware

Handles Cross-Origin Resource Sharing:

corsConfig := &simplehttp.CORSConfig{
    AllowOrigins:     []string{"https://example.com", "https://api.example.com"},
    AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
    AllowHeaders:     []string{"Origin", "Content-Type", "Accept", "Authorization"},
    ExposeHeaders:    []string{"Content-Length"},
    AllowCredentials: true,
    MaxAge:           24 * time.Hour,
}
server.Use(simplehttp.MiddlewareCORS(corsConfig))
RateLimiter Middleware

Prevents abuse by limiting request frequency:

rateConfig := simplehttp.RateLimitConfig{
    RequestsPerSecond: 10,         // Allow 10 requests per second
    BurstSize:         20,         // Allow bursts up to 20 requests
    KeyFunc: func(c simplehttp.Context) string {
        // Rate limit by IP
        headers := c.GetHeaders()
        if headers.RealIP != "" {
            return headers.RealIP
        }
        return headers.RemoteIP
    },
}
server.Use(simplehttp.MiddlewareRateLimiter(rateConfig))
BasicAuth Middleware

Adds HTTP Basic Authentication:

// Global basic auth
server.Use(simplehttp.MiddlewareBasicAuth("admin", "secret"))

// Or apply to specific route groups
adminAPI := server.Group("/admin")
adminAPI.Use(simplehttp.MiddlewareBasicAuth("admin", "admin_password"))
Security Middleware

Adds security-related headers:

secConfig := simplehttp.SecurityConfig{
    FrameDeny:             true,   // Add X-Frame-Options: DENY
    ContentTypeNosniff:    true,   // Add X-Content-Type-Options: nosniff
    BrowserXssFilter:      true,   // Add X-XSS-Protection: 1; mode=block
    ContentSecurityPolicy: "default-src 'self'",
}
server.Use(simplehttp.MiddlewareSecurity(secConfig))
Cache Middleware

Caches responses to improve performance:

cacheConfig := simplehttp.CacheConfig{
    TTL:       5 * time.Minute,
    KeyPrefix: "api:",
    Store:     simplehttp.NewMemoryCache(),
    KeyFunc: func(c simplehttp.Context) string {
        // Cache key based on path and auth
        return c.GetPath() + ":" + c.GetHeader("Authorization")
    },
}
server.Use(simplehttp.MiddlewareCache(cacheConfig))

Creating Custom Middleware

You can create your own middleware to extend SimpleHttp's functionality:

Example: Request Timer Middleware
func RequestTimer() simplehttp.Middleware {
    return simplehttp.WithName("request-timer", func(next simplehttp.HandlerFunc) simplehttp.HandlerFunc {
        return func(c simplehttp.Context) error {
            // Start timing
            start := time.Now()
            
            // Process request
            err := next(c)
            
            // Calculate duration
            duration := time.Since(start)
            
            // Add duration header
            c.SetResponseHeader("X-Request-Duration", duration.String())
            
            return err
        }
    })
}

// Usage
server.Use(RequestTimer())

Route-Specific Middleware

You can apply middleware to specific route groups:

// Global middleware
server.Use(
    simplehttp.MiddlewareRequestID(),
    simplehttp.MiddlewareLogger(logger),
)

// API routes with rate limiting
api := server.Group("/api")
api.Use(simplehttp.MiddlewareRateLimiter(rateConfig))

// Admin routes with authentication
admin := server.Group("/admin")
admin.Use(simplehttp.MiddlewareBasicAuth("admin", "password"))

// Public routes with caching
public := server.Group("/public")
public.Use(simplehttp.MiddlewareCache(cacheConfig))

File Handling

SimpleHttp provides built-in file handling capabilities:

// Setup file handler
fileHandler := simplehttp.NewFileHandler("./uploads")
fileHandler.MaxFileSize = 10 << 20  // 10MB
fileHandler.AllowedTypes = []string{"image/jpeg", "image/png", "application/pdf"}

// File upload endpoint
server.POST("/upload", fileHandler.HandleUpload())

// File download endpoint
server.GET("/files/:filename", fileHandler.HandleDownload("./uploads/{{filename}}"))

WebSockets

SimpleHttp has built-in WebSocket support:

server.WebSocket("/ws/chat", func(ws simplehttp.WebSocket) error {
    for {
        // Read message
        msg := &Message{}
        if err := ws.ReadJSON(msg); err != nil {
            return err
        }
        
        // Process message...
        
        // Send response
        response := &Message{
            Type: "response",
            Data: "Received: " + msg.Data,
        }
        
        if err := ws.WriteJSON(response); err != nil {
            return err
        }
    }
})

Complete Example with Middleware and Route Groups

Here's a more complete example that demonstrates how to use SimpleHttp with various middleware and route groups:

package main

import (
    "context"
    "log"
    "net/http"
    "os"
    "os/signal"
    "time"

    "github.com/medatechnology/simplehttp"
    "github.com/medatechnology/simplehttp/framework/echo"
)

func main() {
    // Load config
    config := simplehttp.LoadConfig()
    
    // Create server
    server := echo.NewServer(config)
    
    // Global middleware
    server.Use(
        simplehttp.MiddlewareRequestID(),
        simplehttp.MiddlewareLogger(simplehttp.NewDefaultLogger()),
        simplehttp.MiddlewareHeaderParser(),
    )
    
    // CORS configuration
    corsConfig := &simplehttp.CORSConfig{
        AllowOrigins:     []string{"*"},
        AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
        AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
        AllowCredentials: true,
        MaxAge:           24 * time.Hour,
    }
    
    // Security configuration
    secConfig := simplehttp.SecurityConfig{
        FrameDeny:          true,
        ContentTypeNosniff: true,
        BrowserXssFilter:   true,
    }
    
    // Rate limit configuration
    rateConfig := simplehttp.RateLimitConfig{
        RequestsPerSecond: 10,
        BurstSize:         20,
        KeyFunc: func(c simplehttp.Context) string {
            headers := c.GetHeaders()
            return headers.RealIP
        },
    }
    
    // Public routes
    server.GET("/", func(c simplehttp.Context) error {
        return c.String(http.StatusOK, "Welcome to SimpleHttp API")
    })
    
    // API routes with additional middleware
    api := server.Group("/api")
    api.Use(
        simplehttp.MiddlewareCORS(corsConfig),
        simplehttp.MiddlewareSecurity(secConfig),
        simplehttp.MiddlewareRateLimiter(rateConfig),
    )
    
    // API endpoints
    api.GET("/status", getStatus)
    
    // Users endpoints
    users := api.Group("/users")
    users.GET("", listUsers)
    users.POST("", createUser)
    users.GET("/:id", getUser)
    users.PUT("/:id", updateUser)
    users.DELETE("/:id", deleteUser)
    
    // Admin endpoints with basic auth
    admin := server.Group("/admin")
    admin.Use(simplehttp.MiddlewareBasicAuth("admin", "secret"))
    admin.GET("/dashboard", adminDashboard)
    
    // File handling
    fileHandler := simplehttp.NewFileHandler("./uploads")
    fileHandler.MaxFileSize = 10 << 20
    server.POST("/upload", fileHandler.HandleUpload())
    server.GET("/files/:filename", fileHandler.HandleDownload("./uploads/{{filename}}"))
    
    // WebSocket endpoint
    server.WebSocket("/ws/chat", handleChat)
    
    // Start server
    go func() {
        if err := server.Start(""); err != nil {
            log.Printf("Server error: %v", err)
        }
    }()
    
    // Graceful shutdown
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt)
    <-quit
    
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    if err := server.Shutdown(ctx); err != nil {
        log.Fatal("Server forced to shutdown:", err)
    }
}

// Handler functions
func getStatus(c simplehttp.Context) error {
    return c.JSON(http.StatusOK, map[string]string{
        "status": "running",
        "version": "1.0.0",
    })
}

func listUsers(c simplehttp.Context) error {
    return c.JSON(http.StatusOK, []map[string]string{
        {"id": "1", "name": "John"},
        {"id": "2", "name": "Jane"},
    })
}

func createUser(c simplehttp.Context) error {
    var user struct {
        Name string `json:"name"`
    }
    if err := c.BindJSON(&user); err != nil {
        return err
    }
    return c.JSON(http.StatusCreated, user)
}

func getUser(c simplehttp.Context) error {
    id := c.GetQueryParam("id")
    return c.JSON(http.StatusOK, map[string]string{
        "id": id,
        "name": "John Doe",
    })
}

func updateUser(c simplehttp.Context) error {
    id := c.GetQueryParam("id")
    var user struct {
        Name string `json:"name"`
    }
    if err := c.BindJSON(&user); err != nil {
        return err
    }
    return c.JSON(http.StatusOK, map[string]string{
        "id": id,
        "name": user.Name,
    })
}

func deleteUser(c simplehttp.Context) error {
    id := c.GetQueryParam("id")
    return c.JSON(http.StatusOK, map[string]string{
        "message": "User " + id + " deleted",
    })
}

func adminDashboard(c simplehttp.Context) error {
    return c.JSON(http.StatusOK, map[string]string{
        "message": "Admin dashboard",
    })
}

func handleChat(ws simplehttp.WebSocket) error {
    for {
        msg := struct {
            Type string `json:"type"`
            Text string `json:"text"`
        }{}
        
        if err := ws.ReadJSON(&msg); err != nil {
            return err
        }
        
        response := struct {
            Type string `json:"type"`
            Text string `json:"text"`
        }{
            Type: "response",
            Text: "Echo: " + msg.Text,
        }
        
        if err := ws.WriteJSON(response); err != nil {
            return err
        }
    }
}

Environment Configuration

SimpleHttp can be configured using environment variables. Here's a complete example of what you can set in your .env file:

# Framework configuration
SIMPLEHTTP_FRAMEWORK=echo              # Framework to use (echo, fiber)
SIMPLEHTTP_APP_NAME=SimpleHttp-App     # Application name
SIMPLEHTTP_HOST_NAME=localhost         # Host name
SIMPLEHTTP_PORT=8080                   # Port to listen on

# Timeout configuration (in seconds)
SIMPLEHTTP_READ_TIMEOUT=30             # HTTP read timeout
SIMPLEHTTP_WRITE_TIMEOUT=30            # HTTP write timeout
SIMPLEHTTP_IDLE_TIMEOUT=60             # HTTP idle timeout

# Debug and logging
SIMPLEHTTP_DEBUG=false                 # Debug mode
SIMPLEHTTP_FRAMEWORK_STARTUP_MESSAGE=true   # Display startup message

Middleware Order

The order in which middleware is applied is important. Middleware is executed in the order it's added:

server.Use(
    // 1. First, add request ID
    simplehttp.MiddlewareRequestID(),
    
    // 2. Then log the incoming request with the ID
    simplehttp.MiddlewareLogger(logger),
    
    // 3. Apply security headers
    simplehttp.MiddlewareSecurity(secConfig),
    
    // 4. Handle CORS
    simplehttp.MiddlewareCORS(corsConfig),
    
    // 5. Apply rate limiting
    simplehttp.MiddlewareRateLimiter(rateConfig),
    
    // 6. Parse headers
    simplehttp.MiddlewareHeaderParser(),
    
    // 7. Finally, set timeout
    simplehttp.MiddlewareTimeout(timeoutConfig),
)

License

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

Documentation

Overview

cache.go

config.go

Index

Constants

View Source
const (
	// in seconds, later converted to time.Duration
	DEFAULT_HTTP_READ_TIMEOUT  = 30
	DEFAULT_HTTP_WRITE_TIMEOUT = 30
	DEFAULT_HTTP_IDLE_TIMEOUT  = 60

	// This was used in fiber
	DEFAULT_HTTP_CONCURRENCY = 512 * 1024

	// environment string
	SIMPLEHTTP_FRAMEWORK                 = "SIMPLEHTTP_FRAMEWORK"
	SIMPLEHTTP_PORT                      = "SIMPLEHTTP_PORT"
	SIMPLEHTTP_APP_NAME                  = "SIMPLEHTTP_APP_NAME"
	SIMPLEHTTP_HOST_NAME                 = "SIMPLEHTTP_HOST_NAME"
	SIMPLEHTTP_READ_TIMEOUT              = "SIMPLEHTTP_READ_TIMEOUT"
	SIMPLEHTTP_WRITE_TIMEOUT             = "SIMPLEHTTP_WRITE_TIMEOUT"
	SIMPLEHTTP_IDLE_TIMEOUT              = "SIMPLEHTTP_IDLE_TIMEOUT"
	SIMPLEHTTP_DEBUG                     = "SIMPLEHTTP_DEBUG"
	SIMPLEHTTP_FRAMEWORK_STARTUP_MESSAGE = "SIMPLEHTTP_FRAMEWORK_STARTUP_MESSAGE"
	SIMPLEHTTP_INTERNAL_API              = "SIMPLEHTTP_INTERNAL_API"
	SIMPLEHTTP_INTERNAL_STATUS           = "SIMPLEHTTP_INTERNAL_STATUS"

	// internal API (if enabled)
	DEFAULT_INTERNAL_API    = "/internal_d" // internal debug
	DEFAULT_INTERNAL_STATUS = "/http_status"
)
View Source
const (
	LogLevelDebug LogLevel = iota
	LogLevelInfo
	LogLevelWarn
	LogLevelError
	LogLevelFatal

	DEFAULT_LOG_TIME_FORMAT = "2006/01/02 15:04:05"
	DEFAULT_LOG_PREFIX      = "[HTTP] "
	DEFAULT_AFTER_HANDLER   = true
	DEFAULT_BEFORE_HANDLER  = false
)

Variables

View Source
var (
	ErrInvalidConfig     = fmt.Errorf("invalid configuration")
	ErrServerStartup     = fmt.Errorf("server startup failed")
	ErrNotFound          = fmt.Errorf("resource not found")
	ErrUnauthorized      = fmt.Errorf("unauthorized")
	ErrForbidden         = fmt.Errorf("forbidden")
	ErrRateLimitExceeded = fmt.Errorf("limit exceeded")
)

Error types

View Source
var (
	// Use this so we can change it on by reading from environment
	PathInternalAPI    string = DEFAULT_INTERNAL_API
	PathInternalStatus string = DEFAULT_INTERNAL_STATUS
)
View Source
var (
	REQUEST_HEADER_PARSED_STRING string = "request_header"

	HEADER_AUTHORIZATION  string = "authorization"
	HEADER_MEDA_API_KEY   string = "MEDA_API_KEY"
	HEADER_API_KEY        string = "API_KEY"
	HEADER_PRIVATE_TOKEN  string = "PRIVATE_TOKEN"
	HEADER_CODE           string = "code"
	HEADER_CONNECTING_IP  string = "CF-Connecting-IP"
	HEADER_FORWARDED_FOR  string = "X-Forwarded-For"
	HEADER_REAL_IP        string = "X-Real-IP"
	HEADER_TRUE_CLIENT_IP string = "True-Client-IP"
	HEADER_USER_AGENT     string = "User-Agent"
	HEADER_ACCEPT_TYPE    string = "Accept"
	HEADER_TRACE_ID       string = "X-Trace-ID"
	HEADER_REQUEST_ID     string = "X-Request-ID"
	HEADER_ORIGIN         string = "Origin"
)
View Source
var DefaultConfig = &Config{
	Framework: "fiber",
	AppName:   "MedaHTTP",
	Hostname:  "localhost",
	Port:      "8080",
	ConfigTimeOut: &TimeOutConfig{
		ReadTimeout:  time.Second * DEFAULT_HTTP_READ_TIMEOUT,
		WriteTimeout: time.Second * DEFAULT_HTTP_WRITE_TIMEOUT,
		IdleTimeout:  time.Second * DEFAULT_HTTP_IDLE_TIMEOUT,
	},
	MaxHeaderBytes:          1 << 20,
	MaxRequestSize:          32 << 20,
	Debug:                   false,
	FrameworkStartupMessage: true,
	Logger:                  NewDefaultLogger(),
	Concurrency:             DEFAULT_HTTP_CONCURRENCY,
}

Default configuration values

Functions

func GenerateRequestID

func GenerateRequestID() string

func ValidateConfig

func ValidateConfig(config *Config) error

Configuration validation

Types

type CORSConfig

type CORSConfig struct {
	AllowOrigins     []string
	AllowMethods     []string
	AllowHeaders     []string
	ExposeHeaders    []string
	AllowCredentials bool
	MaxAge           time.Duration
}

CORSConfig defines CORS settings

type CacheConfig

type CacheConfig struct {
	TTL           time.Duration
	KeyPrefix     string
	KeyFunc       func(Context) string
	Store         CacheStore
	IgnoreHeaders []string
}

Cache middleware configuration

type CacheStore

type CacheStore interface {
	Get(key string) (interface{}, bool)
	Set(key string, value interface{}, ttl time.Duration) error
	Delete(key string) error
	Clear() error
}

Cache defines the interface for cache implementations

func NewMemoryCache

func NewMemoryCache() CacheStore

type CompressionConfig

type CompressionConfig struct {
	Level   int      // Compression level (1-9)
	MinSize int64    // Minimum size to compress
	Types   []string // Content types to compress
}

Compression middleware configuration

type Config

type Config struct {
	Framework string
	AppName   string
	Hostname  string
	Port      string
	// ReadTimeout    time.Duration
	// WriteTimeout   time.Duration
	// IdleTimeout    time.Duration
	MaxHeaderBytes          int
	MaxRequestSize          int64
	UploadDir               string
	TempDir                 string
	TrustedProxies          []string
	Debug                   bool
	FrameworkStartupMessage bool // true means display the default framework startup message, false: quite mode
	Concurrency             int  // for fiber settings

	// TLS Configuration
	TLSCert   string
	TLSKey    string
	AutoTLS   bool
	TLSDomain string

	// Security
	AllowedHosts []string
	SSLRedirect  bool

	// CORS Configuration
	ConfigCORS    *CORSConfig
	ConfigTimeOut *TimeOutConfig

	// Custom error handlers
	ErrorHandler func(error, Context) error

	// Additional components
	Logger Logger // Interface defined in logger.go

}

Configuration holds server settings

func LoadConfig

func LoadConfig() *Config

LoadConfig loads configuration from environment variables

type Context added in v0.0.3

type Context interface {
	// Request information
	GetPath() string
	GetMethod() string
	GetHeader(key string) string
	GetHeaders() *RequestHeader
	SetRequestHeader(key, value string)
	SetResponseHeader(key, value string)
	SetHeader(key, value string)
	GetQueryParam(key string) string
	GetQueryParams() map[string][]string
	GetBody() []byte

	// Added these two methods
	Request() *http.Request
	Response() http.ResponseWriter

	// Response methods
	JSON(code int, data interface{}) error
	String(code int, data string) error
	Stream(code int, contentType string, reader io.Reader) error

	// File handling
	GetFile(fieldName string) (*multipart.FileHeader, error)
	SaveFile(file *multipart.FileHeader, dst string) error
	SendFile(filepath string, attachment bool) error

	// SSE (Server-Sent Events)
	SSE(handler SSEHandler) error

	// Websocket
	Upgrade() (Websocket, error)

	// Context handling
	Context() context.Context
	SetContext(ctx context.Context)
	Set(key string, value interface{})
	Get(key string) interface{}

	// Request binding
	Bind(interface{}) error // Generic binding based on Content-Type
	BindJSON(interface{}) error
	BindForm(interface{}) error
}

Context represents our framework-agnostic request context

type DefaultLogger

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

DefaultLogger holds configuration for DefaultLogger

func (*DefaultLogger) Debug

func (l *DefaultLogger) Debug(v ...interface{})

func (*DefaultLogger) Debugf

func (l *DefaultLogger) Debugf(format string, v ...interface{})

func (*DefaultLogger) Error

func (l *DefaultLogger) Error(v ...interface{})

func (*DefaultLogger) Errorf

func (l *DefaultLogger) Errorf(format string, v ...interface{})

func (*DefaultLogger) Fatal

func (l *DefaultLogger) Fatal(v ...interface{})

func (*DefaultLogger) Fatalf

func (l *DefaultLogger) Fatalf(format string, v ...interface{})

func (*DefaultLogger) Info

func (l *DefaultLogger) Info(v ...interface{})

func (*DefaultLogger) Infof

func (l *DefaultLogger) Infof(format string, v ...interface{})

func (*DefaultLogger) IsAfterHandler added in v0.0.3

func (l *DefaultLogger) IsAfterHandler() bool

func (*DefaultLogger) IsBeforeHandler added in v0.0.3

func (l *DefaultLogger) IsBeforeHandler() bool

Getter

func (*DefaultLogger) IsPrintRequestID added in v0.0.3

func (l *DefaultLogger) IsPrintRequestID() bool

func (*DefaultLogger) Print

func (l *DefaultLogger) Print(v ...interface{})

func (*DefaultLogger) Printf

func (l *DefaultLogger) Printf(format string, v ...interface{})

func (*DefaultLogger) Warn

func (l *DefaultLogger) Warn(v ...interface{})

func (*DefaultLogger) Warnf

func (l *DefaultLogger) Warnf(format string, v ...interface{})

type DefaultLoggerConfig

type DefaultLoggerConfig struct {
	Level          LogLevel // this is the minimum to print out at this log
	BeforeHandler  bool
	AfterHandler   bool
	TimeFormat     string
	Prefix         string
	Output         io.Writer
	PrintRequestID bool
}

type FileHandler

type FileHandler struct {
	UploadDir    string
	MaxFileSize  int64
	AllowedTypes []string
}

File handling utilities

func NewFileHandler

func NewFileHandler(uploadDir string) *FileHandler

func (*FileHandler) HandleDownload

func (h *FileHandler) HandleDownload(filepath string) HandlerFunc

func (*FileHandler) HandleUpload

func (h *FileHandler) HandleUpload() HandlerFunc

This is independent of implementation Make sure the implementation context has .GetFile and .SaveFile

type FileInfo

type FileInfo struct {
	Filename     string
	Size         int64
	ContentType  string
	LastModified time.Time
	Hash         string // MD5/SHA hash of file
}

FileInfo represents uploaded file metadata

type HandlerFunc added in v0.0.3

type HandlerFunc func(Context) error

HandlerFunc is our framework-agnostic handler function

type HeaderAuthorization

type HeaderAuthorization struct {
	Raw   string `db:"authorization"            json:"authorization,omitempty"`
	Type  string `db:"authorization_type"       json:"authorization_type,omitempty"`
	Token string `db:"authorization_token"      json:"authorization_token,omitempty"`
}

type LogLevel

type LogLevel int

type Logger

type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
	Debug(v ...interface{})
	Debugf(format string, v ...interface{})
	Info(v ...interface{})
	Infof(format string, v ...interface{})
	Warn(v ...interface{})
	Warnf(format string, v ...interface{})
	Error(v ...interface{})
	Errorf(format string, v ...interface{})
	Fatal(v ...interface{})
	Fatalf(format string, v ...interface{})
	IsBeforeHandler() bool
	IsAfterHandler() bool
	IsPrintRequestID() bool
}

Logger interface for all logging operations

func NewDefaultLogger

func NewDefaultLogger(config ...*DefaultLoggerConfig) Logger

NewDefaultLogger creates a new DefaultLogger with optional configuration

type MemoryCache

type MemoryCache struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

MemoryCache provides a simple in-memory cache implementation

func (*MemoryCache) Clear

func (c *MemoryCache) Clear() error

func (*MemoryCache) Delete

func (c *MemoryCache) Delete(key string) error

func (*MemoryCache) Get

func (c *MemoryCache) Get(key string) (interface{}, bool)

func (*MemoryCache) Set

func (c *MemoryCache) Set(key string, value interface{}, ttl time.Duration) error

type MemorySession

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

MemorySession provides a simple in-memory session implementation

func (*MemorySession) Clear

func (s *MemorySession) Clear() error

func (*MemorySession) Delete

func (s *MemorySession) Delete(key string) error

func (*MemorySession) Get

func (s *MemorySession) Get(key string) interface{}

func (*MemorySession) ID

func (s *MemorySession) ID() string

func (*MemorySession) Save

func (s *MemorySession) Save() error

func (*MemorySession) Set

func (s *MemorySession) Set(key string, value interface{}) error

type Middleware added in v0.0.3

type Middleware interface {
	Name() string
	Handle(HandlerFunc) HandlerFunc
}

Predefined common Middleware as global variables

func MiddlewareBasicAuth

func MiddlewareBasicAuth(username, password string) Middleware

func MiddlewareCORS

func MiddlewareCORS(config *CORSConfig) Middleware

func MiddlewareCache

func MiddlewareCache(config CacheConfig) Middleware

func MiddlewareCompress

func MiddlewareCompress(config CompressionConfig) Middleware

func MiddlewareHeaderParser

func MiddlewareHeaderParser() Middleware

func MiddlewareLogger

func MiddlewareLogger(log Logger) Middleware

func MiddlewareRateLimiter

func MiddlewareRateLimiter(config RateLimitConfig) Middleware

func MiddlewareRecover

func MiddlewareRecover(config ...RecoverConfig) Middleware

func MiddlewareRequestID

func MiddlewareRequestID() Middleware

func MiddlewareSecurity

func MiddlewareSecurity(config SecurityConfig) Middleware

func MiddlewareTimeout

func MiddlewareTimeout(config TimeOutConfig) Middleware

type MiddlewareFunc added in v0.0.3

type MiddlewareFunc func(HandlerFunc) HandlerFunc

MiddlewareFunc defines the contract for middleware

func BasicAuth

func BasicAuth(username, password string) MiddlewareFunc

func CORS

func CORS(config *CORSConfig) MiddlewareFunc

CORS middleware returns a Middleware that adds CORS headers to the response

func Compress

func Compress(config CompressionConfig) MiddlewareFunc

Compress returns a compression middleware

func HeaderParser

func HeaderParser() MiddlewareFunc

Standard middleware implementations

func RateLimiter

func RateLimiter(config RateLimitConfig) MiddlewareFunc

RateLimiter returns a rate limiting middleware

func Recover

func Recover(config ...RecoverConfig) MiddlewareFunc

Recover returns a middleware that recovers from panics

func RequestID

func RequestID() MiddlewareFunc

RequestID middleware adds a unique ID to each request

func Security

func Security(config SecurityConfig) MiddlewareFunc

Security returns security middleware

func SimpleCache

func SimpleCache(config CacheConfig) MiddlewareFunc

SimpleCache returns a caching middleware

func SimpleLog

func SimpleLog(log Logger) MiddlewareFunc

Print logs for every request (2 lines) [prefix] INFO [date] time [rid] --Started [method] path [prefix] INFO [date] time [rid] Completed [method] path [duration] [prefix] INFO [date] time [rid] Failed [method] path [error] [duration]

func Timeout

func Timeout(config TimeOutConfig) MiddlewareFunc

Timeout middleware adds a timeout to the request context

type NamedMiddleware

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

NamedMiddleware wraps a middleware with a name for debugging

func WithName

func WithName(name string, m MiddlewareFunc) NamedMiddleware

WithName adds a name to a middleware

func (NamedMiddleware) Handle

func (n NamedMiddleware) Handle(next HandlerFunc) HandlerFunc

Implement the SimpleHttpMiddleware interface

func (NamedMiddleware) Name

func (m NamedMiddleware) Name() string

GetMiddlewareName returns the name of the middleware if it's a NamedMiddleware, or "unnamed" if it's a regular middleware

func GetMiddlewareName(m MiddlewareFunc) string {
	if named, ok := m.(*NamedMiddleware); ok {
		return named.name
	}
	return "unnamed"
}

type RateLimit

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

Rate limit, remember burst is usually the one that taking effects (as maximum) Tested OK, it works fine. NOTE: make sure the cache middleware is not interfeering, because that can effect the rateLimit. When it is returned from cache, it doesn't hit the rate limit at all.

func (*RateLimit) Allow

func (rl *RateLimit) Allow(key string) error

type RateLimitConfig

type RateLimitConfig struct {
	RequestsPerSecond int
	BurstSize         int
	ClientTimeout     time.Duration
	KeyFunc           func(Context) string // Function to generate rate limit key
}

RateLimiter middleware configuration

type RecoverConfig

type RecoverConfig struct {
	// StackTrace determines whether to include stack traces in error responses
	StackTrace bool
	// LogStackTrace determines whether to log stack traces
	LogStackTrace bool
	// ErrorHandler is a custom handler for recovered panics
	ErrorHandler func(c Context, err interface{}, stack []byte) error
	// Logger for recording panic information
	Logger Logger
}

RecoverConfig holds configuration for the Recover middleware

type RequestHeader

type RequestHeader struct {
	Authorization HeaderAuthorization `db:"header_authorization"             json:"header_authorization,omitempty"`
	// below are specific to some Meda lib, in this case auth-lib
	MedaAPIKey   string `db:"meda_api_key"        json:"MEDA_API_KEY,omitempty"`
	APIKey       string `db:"api_key"             json:"API_KEY,omitempty"`
	PrivateToken string `db:"private_token"       json:"PRIVATE_TOKEN,omitempty"`
	Code         string `db:"code"                json:"code,omitempty"`
	// standard header
	UserAgent         string `db:"user_agent"          json:"User-Agent,omitempty"`
	AcceptType        string `db:"accept_type"         json:"Accept,omitempty"`
	TraceID           string `db:"trace_id"            json:"X-Trace-ID,omitempty"`
	RequestID         string `db:"request_id"          json:"X-Request-ID,omitempty"`
	Origin            string `db:"origin"              json:"Origin,omitempty"`
	ForwardedFor      string `db:"forwarded_for"       json:"X-Forwarded-For,omitempty"`
	RealIP            string `db:"real_ip"             json:"X-Real-IP,omitempty"`
	ConnectingIP      string `db:"connecting_ip"       json:"CF-Connecting-IP,omitempty"`
	TrueIP            string `db:"true_ip"             json:"true-client-ip,omitempty"`
	RemoteIP          string `db:"remote_ip"           json:"remote-address,omitempty"`
	Browser           string `db:"browser"             json:"browser,omitempty"`
	BrowserVersion    string `db:"browser_version"     json:"browser_version,omitempty"`
	PlatformOS        string `db:"platform_os"         json:"platform_os,omitempty"`
	PlatformOSVersion string `db:"platform_os_version" json:"platform_os_version,omitempty"`
	Platform          string `db:"platform"            json:"platform,omitempty"` // mobile, desktop, unknown
	Device            string `db:"device"              json:"device,omitempty"`   // usually if mobile, this one has value
}

Please change this if RequestHeader struct is changed

func (*RequestHeader) FromHttpRequest

func (mh *RequestHeader) FromHttpRequest(stdRequest *http.Request)

func (*RequestHeader) IP

func (mh *RequestHeader) IP() string

type Router added in v0.0.3

type Router interface {
	GET(path string, handler HandlerFunc)
	POST(path string, handler HandlerFunc)
	PUT(path string, handler HandlerFunc)
	DELETE(path string, handler HandlerFunc)
	PATCH(path string, handler HandlerFunc)
	OPTIONS(path string, handler HandlerFunc)
	HEAD(path string, handler HandlerFunc)

	// Static file serving
	Static(prefix, root string)
	StaticFile(path, filepath string)

	// Websocket
	WebSocket(path string, handler func(Websocket) error)

	Group(prefix string) Router
	Use(middleware ...Middleware)
}

Router interface defines common routing operations

func CreateInternalAPI

func CreateInternalAPI(s Server) Router

type Routes

type Routes struct {
	EndPoint string
	Methods  []string
}

Used to save all endpoints or routes that the server currently handling!

func (*Routes) Sprint

func (r *Routes) Sprint() string

type SSEEvent added in v0.0.8

type SSEEvent struct {
	ID    string // Optional event ID
	Event string // Event type (defaults to "message")
	Data  string // Event data
	Retry int    // Optional retry interval in milliseconds
}

SSEEvent represents a Server-Sent Event

func (SSEEvent) String added in v0.0.8

func (e SSEEvent) String() string

String formats the SSE event for transmission

type SSEHandler added in v0.0.8

type SSEHandler func(SSEWriter) error

SSEHandler is a function that receives an SSEWriter for streaming events

type SSEWriter added in v0.0.8

type SSEWriter interface {
	// Send sends a simple data message
	Send(data string) error
	// SendEvent sends a full SSE event
	SendEvent(event SSEEvent) error
	// Flush flushes the response writer
	Flush()
}

SSEWriter provides methods for writing SSE events

func NewSSEWriter added in v0.0.8

func NewSSEWriter(w http.ResponseWriter) SSEWriter

NewSSEWriter creates a new SSE writer from an http.ResponseWriter

type SecurityConfig

type SecurityConfig struct {
	AllowedHosts          []string
	SSLRedirect           bool
	SSLHost               string
	STSSeconds            int64
	STSIncludeSubdomains  bool
	FrameDeny             bool
	ContentTypeNosniff    bool
	BrowserXssFilter      bool
	ContentSecurityPolicy string
}

Security middleware configuration

type Server added in v0.0.3

type Server interface {
	Router
	Start(address string) error
	Shutdown(ctx context.Context) error
}

Server interface defines the contract for our web server

type Session

type Session interface {
	Get(key string) interface{}
	Set(key string, value interface{}) error
	Delete(key string) error
	Clear() error
	ID() string
	Save() error
}

Session defines the interface for session management

func NewMemorySession

func NewMemorySession(id string) Session

type SimpleHttpError added in v0.0.3

type SimpleHttpError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Details interface{} `json:"details,omitempty"`
}

SimpleHttpError represents a standardized error response

func NewError

func NewError(code int, message string, details ...interface{}) *SimpleHttpError

NewError creates a new SimpleHttpError

func (*SimpleHttpError) Error added in v0.0.3

func (e *SimpleHttpError) Error() string

type TimeOutConfig

type TimeOutConfig struct {
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
	IdleTimeout  time.Duration
}

type Websocket added in v0.0.3

type Websocket interface {
	WriteJSON(v interface{}) error
	ReadJSON(v interface{}) error
	WriteMessage(messageType int, data []byte) error
	ReadMessage() (messageType int, p []byte, err error)
	Close() error
}

Websocket interface for websocket connections

Directories

Path Synopsis
examples/echo/main.go
examples/echo/main.go
framework
echo
framework/echo/adapter.go
framework/echo/adapter.go
fasthttp
framework/fasthttp/adapter.go
framework/fasthttp/adapter.go
fiber
framework/fiber/adapter.go
framework/fiber/adapter.go

Jump to

Keyboard shortcuts

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