echo

package
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: 10 Imported by: 0

README

Echo Implementation Guide

This guide demonstrates how to use the Echo framework implementation with MedaHTTP.

Installation

go get github.com/medatechnology/simplehttp/framework/echo

Basic Usage

Here's a simple example of using MedaHTTP with Echo:

package main

import (
    "log"
    
    "github.com/medatechnology/simplehttp"
    "github.com/medatechnology/simplehttp/framework/echo"
)

func main() {
    // Load configuration
    config := simplehttp.LoadConfig()
    
    // Create Echo server
    server := echo.NewServer(config)
    
    // Add middleware
    server.Use(
        simplehttp.RequestID(),
        simplehttp.LoggerMiddleware(simplehttp.NewDefaultLogger()),
        simplehttp.HeaderParser(),
    )
    
    // Define routes
    server.GET("/", handleHome)
    server.POST("/api/users", handleCreateUser)
    
    // Start server
    if err := server.Start(":8080"); err != nil {
        log.Fatal(err)
    }
}

func handleHome(c simplehttp.Context) error {
    return c.JSON(200, map[string]string{
        "message": "Welcome to SimpleHTTP with Echo!",
    })
}

func handleCreateUser(c simplehttp.Context) error {
    var user struct {
        Name  string `json:"name"`
        Email string `json:"email"`
    }
    
    if err := c.BindJSON(&user); err != nil {
        return err
    }
    
    // Process user...
    
    return c.JSON(201, user)
}

Complete Example

Here's a more comprehensive example showing various features:

package main

import (
    "log"
    "time"
    
    "github.com/medatechnology/simplehttp"
    "github.com/medatechnology/simplehttp/framework/echo"
)

type App struct {
    server simplehttp.Server
    logger simplehttp.Logger
}

func NewApp() *App {
    // Load configuration
    config := simplehttp.LoadConfig()
    
    // Create logger
    logger := simplehttp.NewDefaultLogger(&simplehttp.DefaultLoggerConfig{
        Level:      simplehttp.LogLevelDebug,
        TimeFormat: "2006/01/02 15:04:05",
        Prefix:     "[APP] ",
    })
    
    // Create server
    server := echo.NewServer(config)
    
    return &App{
        server: server,
        logger: logger,
    }
}

func (app *App) setupMiddleware() {
    // Basic middleware
    app.server.Use(
        simplehttp.RequestID(),
        simplehttp.LoggerMiddleware(app.logger),
        simplehttp.HeaderParser(),
    )
    
    // Security middleware
    app.server.Use(
        simplehttp.Security(simplehttp.SecurityConfig{
            ContentTypeNosniff: true,
            BrowserXssFilter:  true,
            FrameDeny:        true,
        }),
    )
    
    // Rate limiting
    app.server.Use(
        simplehttp.RateLimiter(simplehttp.RateLimitConfig{
            RequestsPerSecond: 10,
            BurstSize:        20,
            KeyFunc: func(c simplehttp.Context) string {
                return c.GetHeader("X-Real-IP")
            },
        }),
    )
    
    // CORS
    app.server.Use(
        simplehttp.CORS(&simplehttp.CORSConfig{
            AllowOrigins:     []string{"*"},
            AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
            AllowHeaders:     []string{"Origin", "Content-Type", "Accept"},
            AllowCredentials: true,
            MaxAge:          24 * time.Hour,
        }),
    )
}

func (app *App) setupRoutes() {
    // API routes
    api := app.server.Group("/api")
    {
        // User routes
        users := api.Group("/users")
        users.GET("", app.handleListUsers)
        users.POST("", app.handleCreateUser)
        users.GET("/:id", app.handleGetUser)
        
        // File upload routes
        files := api.Group("/files")
        fileHandler := simplehttp.NewFileHandler("./uploads")
        files.POST("/upload", fileHandler.HandleUpload())
        files.GET("/download/:filename", fileHandler.HandleDownload("./uploads"))
    }
    
    // WebSocket route
    app.server.WebSocket("/ws", app.handleWebSocket)
}

func (app *App) handleListUsers(c simplehttp.Context) error {
    users := []map[string]string{
        {"id": "1", "name": "John Doe"},
        {"id": "2", "name": "Jane Doe"},
    }
    return c.JSON(200, users)
}

func (app *App) handleCreateUser(c simplehttp.Context) error {
    var user struct {
        Name  string `json:"name"`
        Email string `json:"email"`
    }
    
    if err := c.BindJSON(&user); err != nil {
        return err
    }
    
    // Validate headers
    headers := c.GetHeaders()
    if headers.APIKey == "" {
        return simplehttp.NewError(401, "API key required")
    }
    
    return c.JSON(201, user)
}

func (app *App) handleGetUser(c simplehttp.Context) error {
    id := c.GetQueryParam("id")
    user := map[string]string{
        "id":    id,
        "name":  "John Doe",
        "email": "john@example.com",
    }
    return c.JSON(200, user)
}

func (app *App) handleWebSocket(ws simplehttp.WebSocket) error {
    for {
        var msg struct {
            Type    string `json:"type"`
            Content string `json:"content"`
        }
        
        if err := ws.ReadJSON(&msg); err != nil {
            return err
        }
        
        response := map[string]string{
            "type":    "response",
            "content": "Received: " + msg.Content,
        }
        
        if err := ws.WriteJSON(response); err != nil {
            return err
        }
    }
}

func main() {
    app := NewApp()
    
    app.setupMiddleware()
    app.setupRoutes()
    
    if err := app.server.Start(":8080"); err != nil {
        log.Fatal(err)
    }
}

Framework-Specific Notes

When using the Echo implementation:

  1. Context Access: You can access the underlying Echo context if needed:

    echoCtx := c.Get("echo.context").(*echo.Context)
    
  2. File Uploads: Echo's multipart file handling is automatically wrapped:

    file, err := c.GetFile("upload")
    if err != nil {
        return err
    }
    
  3. WebSocket: The Echo implementation uses gorilla/websocket internally:

    server.WebSocket("/ws", func(ws simplehttp.WebSocket) error {
        // WebSocket connection handler
    })
    

Testing

Here's an example of how to test your Echo implementation:

package main

import (
    "net/http/httptest"
    "testing"
    
    "github.com/stretchr/testify/assert"
    "github.com/medatechnology/simplehttp"
    "github.com/medatechnology/simplehttp/framework/echo"
)

func TestEchoServer(t *testing.T) {
    // Create server
    config := simplehttp.LoadConfig()
    server := echo.NewServer(config)
    
    // Add test route
    server.GET("/test", func(c simplehttp.Context) error {
        return c.JSON(200, map[string]string{"message": "success"})
    })
    
    // Create test request
    req := httptest.NewRequest("GET", "/test", nil)
    rec := httptest.NewRecorder()
    
    // Serve request
    server.ServeHTTP(rec, req)
    
    // Assert response
    assert.Equal(t, 200, rec.Code)
    assert.Contains(t, rec.Body.String(), "success")
}

Best Practices

  1. Configuration: Always use environment variables for configuration:

    export SIMPLEHTTP_FRAMEWORK=echo
    export SIMPLEHTTP_PORT=8080
    export SIMPLEHTTP_READ_TIMEOUT=30
    
  2. Middleware Order: Consider the order of middleware:

    • RequestID (first to track requests)
    • Logger (early to log all requests)
    • Security middleware
    • CORS
    • Rate limiting
    • Your custom middleware
  3. Error Handling: Use the built-in error types:

    if err != nil {
        return simplehttp.NewError(500, "Internal error", err)
    }
    
  4. Graceful Shutdown: Implement graceful shutdown:

    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    go func() {
        <-c
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        defer cancel()
        if err := server.Shutdown(ctx); err != nil {
            log.Fatal(err)
        }
    }()
    

Documentation

Overview

framework/echo/adapter.go

framework/echo/context.go

framework/echo/server.go

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Adapter

func Adapter(handler simplehttp.HandlerFunc) echo.HandlerFunc

Adapter converts SimpleHttp HandlerFunc to echo.HandlerFunc

func MiddlewareAdapter

func MiddlewareAdapter(middleware simplehttp.MiddlewareFunc) echo.MiddlewareFunc

MiddlewareAdapter converts SimpleHttp Middleware to echo.MiddlewareFunc

func NewEchoContext

func NewEchoContext(c echo.Context, cfgs ...*simplehttp.Config) simplehttp.Context

func NewServer

func NewServer(config *simplehttp.Config) simplehttp.Server

Types

type EchoContext

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

EchoContext implements MedaContext interface using Echo's Context

func (*EchoContext) Bind

func (c *EchoContext) Bind(v interface{}) error

func (*EchoContext) BindForm

func (c *EchoContext) BindForm(i interface{}) error

func (*EchoContext) BindJSON

func (c *EchoContext) BindJSON(i interface{}) error

func (*EchoContext) Context

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

func (*EchoContext) Get

func (c *EchoContext) Get(key string) interface{}

func (*EchoContext) GetBody

func (c *EchoContext) GetBody() []byte

func (*EchoContext) GetFile

func (c *EchoContext) GetFile(fieldName string) (*multipart.FileHeader, error)

func (*EchoContext) GetHeader

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

func (*EchoContext) GetHeaders

func (c *EchoContext) GetHeaders() *simplehttp.RequestHeader

func (*EchoContext) GetMethod

func (c *EchoContext) GetMethod() string

func (*EchoContext) GetPath

func (c *EchoContext) GetPath() string

func (*EchoContext) GetQueryParam

func (c *EchoContext) GetQueryParam(key string) string

func (*EchoContext) GetQueryParams

func (c *EchoContext) GetQueryParams() map[string][]string

func (*EchoContext) JSON

func (c *EchoContext) JSON(code int, data interface{}) error

func (*EchoContext) Request

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

func (*EchoContext) Response

func (c *EchoContext) Response() http.ResponseWriter

func (*EchoContext) SSE added in v0.0.8

func (c *EchoContext) SSE(handler simplehttp.SSEHandler) error

SSE starts a Server-Sent Events stream

func (*EchoContext) SaveFile

func (c *EchoContext) SaveFile(file *multipart.FileHeader, dst string) error

func (*EchoContext) SendFile

func (c *EchoContext) SendFile(filepath string, attachment bool) error

func (*EchoContext) Set

func (c *EchoContext) Set(key string, value interface{})

func (*EchoContext) SetContext

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

func (*EchoContext) SetHeader

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

func (*EchoContext) SetRequestHeader

func (c *EchoContext) SetRequestHeader(key, value string)

func (*EchoContext) SetResponseHeader

func (c *EchoContext) SetResponseHeader(key, value string)

func (*EchoContext) Stream

func (c *EchoContext) Stream(code int, contentType string, reader io.Reader) error

func (*EchoContext) String

func (c *EchoContext) String(code int, data string) error

func (*EchoContext) Upgrade

func (c *EchoContext) Upgrade() (simplehttp.Websocket, error)

type EchoGroup

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

EchoGroup implements MedaRouter interface for route groups

func (*EchoGroup) DELETE

func (g *EchoGroup) DELETE(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) GET

func (g *EchoGroup) GET(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) Group

func (g *EchoGroup) Group(prefix string) simplehttp.Router

func (*EchoGroup) HEAD

func (g *EchoGroup) HEAD(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) OPTIONS

func (g *EchoGroup) OPTIONS(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) PATCH

func (g *EchoGroup) PATCH(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) POST

func (g *EchoGroup) POST(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) PUT

func (g *EchoGroup) PUT(path string, handler simplehttp.HandlerFunc)

func (*EchoGroup) Static

func (g *EchoGroup) Static(prefix, root string)

func (*EchoGroup) StaticFile

func (g *EchoGroup) StaticFile(path, filepath string)

func (*EchoGroup) Use

func (g *EchoGroup) Use(middleware ...simplehttp.Middleware)

func (*EchoGroup) WebSocket

func (g *EchoGroup) WebSocket(path string, handler func(simplehttp.Websocket) error)

type EchoServer

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

func (*EchoServer) DELETE

func (s *EchoServer) DELETE(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) GET

func (s *EchoServer) GET(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) Group

func (s *EchoServer) Group(prefix string) simplehttp.Router

func (*EchoServer) HEAD

func (s *EchoServer) HEAD(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) OPTIONS

func (s *EchoServer) OPTIONS(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) PATCH

func (s *EchoServer) PATCH(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) POST

func (s *EchoServer) POST(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) PUT

func (s *EchoServer) PUT(path string, handler simplehttp.HandlerFunc)

func (*EchoServer) Shutdown

func (s *EchoServer) Shutdown(ctx context.Context) error

Shutdown is a no-op in Echo v5 as it's handled internally

func (*EchoServer) Start

func (s *EchoServer) Start(address string) error

func (*EchoServer) Static

func (s *EchoServer) Static(prefix, root string)

func (*EchoServer) StaticFile

func (s *EchoServer) StaticFile(path, filepath string)

func (*EchoServer) Use

func (s *EchoServer) Use(middleware ...simplehttp.Middleware)

func (*EchoServer) WebSocket

func (s *EchoServer) WebSocket(path string, handler func(simplehttp.Websocket) error)

type EchoWebSocket

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

EchoWebSocket implements MedaWebsocket interface using gorilla

func (*EchoWebSocket) Close

func (ws *EchoWebSocket) Close() error

func (*EchoWebSocket) ReadJSON

func (ws *EchoWebSocket) ReadJSON(v interface{}) error

func (*EchoWebSocket) ReadMessage

func (ws *EchoWebSocket) ReadMessage() (messageType int, p []byte, err error)

func (*EchoWebSocket) WriteJSON

func (ws *EchoWebSocket) WriteJSON(v interface{}) error

func (*EchoWebSocket) WriteMessage

func (ws *EchoWebSocket) WriteMessage(messageType int, data []byte) error

Jump to

Keyboard shortcuts

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