simplehttp

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Apr 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.)
MEDA_FRAMEWORK=echo

# Application settings
MEDA_APP_NAME=MyAPIService
MEDA_PORT=8080
MEDA_HOST_NAME=localhost

# Timeouts in seconds
MEDA_READ_TIMEOUT=30
MEDA_WRITE_TIMEOUT=30
MEDA_IDLE_TIMEOUT=60

# Debug mode
MEDA_DEBUG=false

# Display startup message
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.MedaContext) error {
        return c.String(http.StatusOK, "Hello, World!")
    })

    api := server.Group("/api")
    {
        api.GET("/status", func(c simplehttp.MedaContext) 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.MedaContext) 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.MedaContext) 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.MedaContext) 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.MedaMiddleware {
    return simplehttp.WithName("request-timer", func(next simplehttp.MedaHandlerFunc) simplehttp.MedaHandlerFunc {
        return func(c simplehttp.MedaContext) 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.MedaWebsocket) 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.MedaContext) string {
            headers := c.GetHeaders()
            return headers.RealIP
        },
    }
    
    // Public routes
    server.GET("/", func(c simplehttp.MedaContext) 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.MedaContext) error {
    return c.JSON(http.StatusOK, map[string]string{
        "status": "running",
        "version": "1.0.0",
    })
}

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

func createUser(c simplehttp.MedaContext) 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.MedaContext) error {
    id := c.GetQueryParam("id")
    return c.JSON(http.StatusOK, map[string]string{
        "id": id,
        "name": "John Doe",
    })
}

func updateUser(c simplehttp.MedaContext) 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.MedaContext) error {
    id := c.GetQueryParam("id")
    return c.JSON(http.StatusOK, map[string]string{
        "message": "User " + id + " deleted",
    })
}

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

func handleChat(ws simplehttp.MedaWebsocket) 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
MEDA_FRAMEWORK=echo              # Framework to use (echo, fiber)
MEDA_APP_NAME=SimpleHttp-App     # Application name
MEDA_HOST_NAME=localhost         # Host name
MEDA_PORT=8080                   # Port to listen on

# Timeout configuration (in seconds)
MEDA_READ_TIMEOUT=30             # HTTP read timeout
MEDA_WRITE_TIMEOUT=30            # HTTP write timeout
MEDA_IDLE_TIMEOUT=60             # HTTP idle timeout

# Debug and logging
MEDA_DEBUG=false                 # Debug mode
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
	MEDA_DEFAULT_HTTP_READ_TIMEOUT  = 30
	MEDA_DEFAULT_HTTP_WRITE_TIMEOUT = 30
	MEDA_DEFAULT_HTTP_IDLE_TIMEOUT  = 60

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

	// environment string
	MEDA_FRAMEWORK            = "MEDA_FRAMEWORK"
	MEDA_PORT                 = "MEDA_PORT"
	MEDA_APP_NAME             = "MEDA_APP_NAME"
	MEDA_HOST_NAME            = "MEDA_HOST_NAME"
	MEDA_READ_TIMEOUT         = "MEDA_READ_TIMEOUT"
	MEDA_WRITE_TIMEOUT        = "MEDA_WRITE_TIMEOUT"
	MEDA_IDLE_TIMEOUT         = "MEDA_IDLE_TIMEOUT"
	MEDA_DEBUG                = "MEDA_DEBUG"
	FRAMEWORK_STARTUP_MESSAGE = "FRAMEWORK_STARTUP_MESSAGE"
	INTERNAL_API              = "DEFAULT_INTERNAL_API"
	INTERNAL_STATUS           = "DEFAULT_INTERNAL_STATUS"

	// internal API (if enabled)
	DEFAULT_INTERNAL_API    = "/internal_d" // internal debug
	DEFAULT_INTERNAL_STATUS = "/http_status"
)
View Source
const (
	REQUEST_HEADER_PARSED_STRING = "request_header"

	HEADER_AUTHORIZATION  = "authorization"
	HEADER_MEDA_API_KEY   = "MEDA_API_KEY"
	HEADER_PRIVATE_TOKEN  = "PRIVATE_TOKEN"
	HEADER_CODE           = "code"
	HEADER_CONNECTING_IP  = "CF-Connecting-IP"
	HEADER_FORWARDED_FOR  = "X-Forwarded-For"
	HEADER_REAL_IP        = "X-Real-IP"
	HEADER_TRUE_CLIENT_IP = "True-Client-IP"
	HEADER_USER_AGENT     = "User-Agent"
	HEADER_ACCEPT_TYPE    = "Accept"
	HEADER_TRACE_ID       = "X-Trace-ID"
	HEADER_REQUEST_ID     = "X-Request-ID"
	HEADER_ORIGIN         = "Origin"
)

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 DefaultConfig = &Config{
	Framework: "fiber",
	AppName:   "MedaHTTP",
	Hostname:  "localhost",
	Port:      "8080",
	ConfigTimeOut: &TimeOutConfig{
		ReadTimeout:  time.Second * MEDA_DEFAULT_HTTP_READ_TIMEOUT,
		WriteTimeout: time.Second * MEDA_DEFAULT_HTTP_WRITE_TIMEOUT,
		IdleTimeout:  time.Second * MEDA_DEFAULT_HTTP_IDLE_TIMEOUT,
	},
	MaxHeaderBytes:          1 << 20,
	MaxRequestSize:          32 << 20,
	Debug:                   false,
	FrameworkStartupMessage: true,
	Logger:                  NewDefaultLogger(),
	Concurrency:             MEDA_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(MedaContext) 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, MedaContext) 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 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) 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
	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) MedaHandlerFunc

func (*FileHandler) HandleUpload

func (h *FileHandler) HandleUpload() MedaHandlerFunc

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 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
const (
	LogLevelDebug LogLevel = iota
	LogLevelInfo
	LogLevelWarn
	LogLevelError
	LogLevelFatal

	DEFAULT_LOG_TIME_FORMAT = "2006/01/02 15:04:05"
	DEFAULT_LOG_PREFIX      = "[MEDA] "
)

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{})
}

Logger interface for all logging operations

func NewDefaultLogger

func NewDefaultLogger(config ...*DefaultLoggerConfig) Logger

NewDefaultLogger creates a new DefaultLogger with optional configuration

type MedaContext

type MedaContext 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

	// Websocket
	Upgrade() (MedaWebsocket, 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
}

MedaContext represents our framework-agnostic request context

type MedaError

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

MedaError represents a standardized error response

func NewError

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

NewError creates a new MedaError

func (*MedaError) Error

func (e *MedaError) Error() string

type MedaHandlerFunc

type MedaHandlerFunc func(MedaContext) error

MedaHandlerFunc is our framework-agnostic handler function

type MedaMiddleware

type MedaMiddleware interface {
	Name() string
	Handle(MedaHandlerFunc) MedaHandlerFunc
}

Predefined common MedaMiddleware as global variables

func MiddlewareBasicAuth

func MiddlewareBasicAuth(username, password string) MedaMiddleware

func MiddlewareCORS

func MiddlewareCORS(config *CORSConfig) MedaMiddleware

func MiddlewareCache

func MiddlewareCache(config CacheConfig) MedaMiddleware

func MiddlewareCompress

func MiddlewareCompress(config CompressionConfig) MedaMiddleware

func MiddlewareHeaderParser

func MiddlewareHeaderParser() MedaMiddleware

func MiddlewareLogger

func MiddlewareLogger(log Logger) MedaMiddleware

func MiddlewareRateLimiter

func MiddlewareRateLimiter(config RateLimitConfig) MedaMiddleware

func MiddlewareRecover

func MiddlewareRecover(config ...RecoverConfig) MedaMiddleware

func MiddlewareRequestID

func MiddlewareRequestID() MedaMiddleware

func MiddlewareSecurity

func MiddlewareSecurity(config SecurityConfig) MedaMiddleware

func MiddlewareTimeout

func MiddlewareTimeout(config TimeOutConfig) MedaMiddleware

type MedaMiddlewareFunc

type MedaMiddlewareFunc func(MedaHandlerFunc) MedaHandlerFunc

MedaMiddlewareFunc defines the contract for middleware

func BasicAuth

func BasicAuth(username, password string) MedaMiddlewareFunc

func CORS

func CORS(config *CORSConfig) MedaMiddlewareFunc

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

func Compress

func Compress(config CompressionConfig) MedaMiddlewareFunc

Compress returns a compression middleware

func HeaderParser

func HeaderParser() MedaMiddlewareFunc

Standard middleware implementations

func RateLimiter

func RateLimiter(config RateLimitConfig) MedaMiddlewareFunc

RateLimiter returns a rate limiting middleware

func Recover

func Recover(config ...RecoverConfig) MedaMiddlewareFunc

Recover returns a middleware that recovers from panics

func RequestID

func RequestID() MedaMiddlewareFunc

RequestID middleware adds a unique ID to each request

func Security

func Security(config SecurityConfig) MedaMiddlewareFunc

Security returns security middleware

func SimpleCache

func SimpleCache(config CacheConfig) MedaMiddlewareFunc

SimpleCache returns a caching middleware

func SimpleLog

func SimpleLog(log Logger) MedaMiddlewareFunc

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) MedaMiddlewareFunc

Timeout middleware adds a timeout to the request context

type MedaRouter

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

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

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

	Group(prefix string) MedaRouter
	Use(middleware ...MedaMiddleware)
}

MedaRouter interface defines common routing operations

func CreateInternalAPI

func CreateInternalAPI(s MedaServer) MedaRouter

type MedaServer

type MedaServer interface {
	MedaRouter
	Start(address string) error
	Shutdown(ctx context.Context) error
}

MedaServer interface defines the contract for our web server

type MedaWebsocket

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

MedaWebsocket interface for websocket connections

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 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 MedaMiddlewareFunc) NamedMiddleware

WithName adds a name to a middleware

func (NamedMiddleware) Handle

Implement the MedaMiddleware 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 MedaMiddlewareFunc) 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(MedaContext) 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 MedaContext, 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
	APIKey       string `db:"api_key"             json:"MEDA_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 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 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 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 TimeOutConfig

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

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