Skip to content

EpicServer is a library on top of Go Gin that provides helpful methods for, Middleware, Authentication, OAuth provider setup and exposes hooks to customise behaivour.

Notifications You must be signed in to change notification settings

tomskip123/EpicServer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EpicServer

A powerful, flexible, and production-ready Go web server built on top of Gin framework.

Go Version

Version

Table of Contents

  1. Getting Started

  2. Core Features

  3. Advanced Usage

  4. Security

  5. API Reference

  6. Contributing

  7. License

  8. Support

Getting Started

Installation

go get github.com/tomskip123/EpicServer

Quick Start

Create a new web server in just a few lines:

package main

import "github.com/tomskip123/EpicServer"

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })

    server.UpdateAppLayer([]EpicServer.AppLayer{
        EpicServer.WithHealthCheck("/health"),
        EpicServer.WithEnvironment("development"),
    })

    server.Start()
}

Basic Example

Here's a complete example with routing, database, and authentication:

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/tomskip123/EpicServer"
    "github.com/tomskip123/EpicServer/db"
)

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetHost("localhost", 8080),
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })

    server.UpdateAppLayer([]EpicServer.AppLayer{
        EpicServer.WithRoutes(
            EpicServer.RouteGroup{
                Prefix: "/api/v1",
                Routes: []EpicServer.Route{
                    EpicServer.Get("/users", HandleUsers),
                },
            },
        ),
        EpicServerDb.WithMongo(&EpicServerDb.MongoConfig{
            ConnectionName: "default",
            URI:           "mongodb://localhost:27017",
            DatabaseName:  "myapp",
        }),
    })

    server.Start()
}

func HandleUsers(c *gin.Context, s *EpicServer.Server) {
    client := EpicServerDb.GetMongoClient(s, "default")
    db := client.Database("myapp")
    collection := db.Collection("users")
    // Handle request using MongoDB...
    c.JSON(200, gin.H{"message": "users endpoint"})
}

Core Features

Configuration System

EpicServer provides a flexible configuration system using options pattern.

Basic Configuration

package main

import (
    "github.com/tomskip123/EpicServer"
)

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetHost("localhost", 8080),
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })
}

Available Configuration Options

The Config struct supports the following configurations:

type Config struct {
    Server struct {
        Host        string
        Port        int
        Environment string
    }
    Security struct {
        SecureCookie bool
        CookieDomain string
        CSPHeader    string
        Origins      []string
    }
    SecretKey []byte
    Custom    interface{}
}

Setting Server Options

Configure server host and port:

EpicServer.SetHost("0.0.0.0", 3000)

Setting Security Options

Configure secret key for encryption:

EpicServer.SetSecretKey([]byte("32-byte-long-secret-key-here...."))

Routing

EpicServer provides a flexible routing system that allows you to organize your routes into groups and access server instance in your handlers.

Basic Route Setup

package main

import (
    "github.com/tomskip123/EpicServer"
)

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Configure routes
            EpicServer.WithRoutes(
                EpicServer.RouteGroup{
                    Prefix: "/api/v1",
                    Routes: []EpicServer.Route{
                        EpicServer.Get("/users", HandleGetUsers),
                        EpicServer.Post("/users", HandleCreateUser),
                        EpicServer.Put("/users/:id", HandleUpdateUser),
                        EpicServer.Delete("/users/:id", HandleDeleteUser),
                    },
                },
                EpicServer.RouteGroup{
                    Prefix: "/admin",
                    Routes: []EpicServer.Route{
                        EpicServer.Get("/stats", HandleAdminStats),
                    },
                },
            ),
        },
    })

    server.Start()
}

Route Handlers

Route handlers have access to both the Gin context and the server instance:

func HandleGetUsers(c *gin.Context, s *EpicServer.Server) {
    // Access server components
    db := EpicServerDb.GetMongoClient(s, "default")
    cache := EpicServerCache.GetMemoryCache(s, "myCache")
    
    // Use gin context as normal
    userId := c.Param("id")
    query := c.Query("filter")
    
    // Send response
    c.JSON(200, gin.H{"message": "success"})
}

Available Route Methods

  • Get(path string, handler HandlerFunc) - HTTP GET
  • Post(path string, handler HandlerFunc) - HTTP POST
  • Put(path string, handler HandlerFunc) - HTTP PUT
  • Patch(path string, handler HandlerFunc) - HTTP PATCH
  • Delete(path string, handler HandlerFunc) - HTTP DELETE

Route Groups

Group related routes with common prefix:

EpicServer.WithRoutes(
    EpicServer.RouteGroup{
        Prefix: "/api/v1",
        Routes: []EpicServer.Route{
            // All routes here will be prefixed with /api/v1
        },
    },
)

Accessing Server Components

Route handlers can access all server components:

func MyHandler(c *gin.Context, s *EpicServer.Server) {
    // Access configuration
    port := s.Config.Server.Port
    
    // Access logger
    s.Logger.Info("Handling request")
    
    // Access authentication
    session, _ := EpicServer.GetSession(c)
    
    // Access databases
    mongoClient := EpicServerDb.GetMongoClient(s, "mongodb")
    postgresDB := EpicServerDb.GetPostgresDB(s, "postgres")
    
    // Access cache
    cache := EpicServerCache.GetMemoryCache(s, "mycache")
    
    // Access hooks
    s.Hooks.Auth.OnUserCreate(claims)
}

Authentication

EpicServer provides a flexible authentication system supporting multiple providers and custom authentication hooks.

Setting Up Authentication

package main

import (
    "github.com/tomskip123/EpicServer"
)

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Configure authentication
            EpicServer.WithAuth([]EpicServer.Provider{
                {
                    Name:         "google",
                    ClientId:     "your-client-id",
                    ClientSecret: "your-client-secret",
                    Callback:     "http://localhost:3000/auth/google/callback",
                },
            }, &EpicServer.SessionConfig{
                CookieName:      "auth_session",
                CookieDomain:    "localhost",
                CookieSecure:    false,
                CookieHTTPOnly:  true,
                SessionDuration: time.Hour * 24,
            }),
            // Add authentication middleware
            EpicServer.WithAuthMiddleware(EpicServer.SessionConfig{
                CookieName:   "auth_session",
                CookieDomain: "localhost",
                CookieSecure: false,
            }),
        },
    })

    server.Start()
}

Configuring Public Paths

Define paths that don't require authentication:

EpicServer.WithPublicPaths(EpicServer.PublicPathConfig{
    Exact: []string{
        "/health",
        "/login",
    },
    Prefix: []string{
        "/public",
        "/api/v1/public",
    },
})

Custom Authentication Hooks

Implement custom authentication logic:

type MyAuthHooks struct {
    db *Database
}

func (h *MyAuthHooks) OnUserCreate(user EpicServer.Claims) (string, error) {
    // Create user in database
    return userID, nil
}

func (h *MyAuthHooks) GetUserOrCreate(user EpicServer.Claims) (*EpicServer.CookieContents, error) {
    // Get or create user and return session data
    return &EpicServer.CookieContents{
        UserId:     user.UserID,
        Email:      user.Email,
        SessionId:  generateSessionID(),
        IsLoggedIn: true,
        ExpiresOn:  time.Now().Add(time.Hour * 24),
    }, nil
}

// Add auth hooks to server
server.UpdateAppLayer([]EpicServer.AppLayer{
    EpicServer.WithAuthHooks(&MyAuthHooks{db: db}),
})

Available Auth Providers

  • Google ("google")
  • Basic Auth ("basic")
  • Custom providers can be added by implementing the provider interface

Environment Variables

Required environment variables for secure authentication:

SECURE_COOKIE_HASH_KEY=base64_encoded_32_byte_key
SECURE_COOKIE_BLOCK_KEY=base64_encoded_32_byte_key
ENCRYPTION_KEY=32_byte_hex_encoded_key

Generate secure keys using:

hashKey, _ := EpicServer.GenerateEncryptionKey()
blockKey, _ := EpicServer.GenerateEncryptionKey()

Authentication Endpoints

The following endpoints are automatically created:

  • /auth/:provider - Initiates authentication flow
  • /auth/:provider/callback - OAuth callback URL
  • /auth/logout - Handles user logout

Session Management

Access session data in your handlers:

func MyProtectedHandler(c *gin.Context) {
    session, err := EpicServer.GetSession(c)
    if err != nil {
        c.AbortWithStatus(401)
        return
    }
    
    // Access session data
    userEmail := session.Email
    userData := session.User
}

Database Support

EpicServer supports multiple database adapters out of the box:

MongoDB

package main

import (
    "github.com/tomskip123/EpicServer"
    "github.com/tomskip123/EpicServer/db"
)

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })

    server.UpdateAppLayer([]EpicServer.AppLayer{
        // Configure MongoDB
        EpicServerDb.WithMongo(&EpicServerDb.MongoConfig{
            ConnectionName: "default",
            URI:           "mongodb://localhost:27017",
            DatabaseName:  "myapp",
        }),
    })

    server.Start()
}

func HandleUsers(c *gin.Context, s *EpicServer.Server) {
    client := EpicServerDb.GetMongoClient(s, "default")
    db := client.Database("myapp")
    collection := db.Collection("users")
    // Handle request using MongoDB...
}

PostgreSQL

package main

import (
    "github.com/tomskip123/EpicServer"
    "github.com/tomskip123/EpicServer/db"
)

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })

    server.UpdateAppLayer([]EpicServer.AppLayer{
        // Configure PostgreSQL
        EpicServerDb.WithPostgres(EpicServerDb.PostgresConfig{
            ConnectionName: "default",
            Host:          "localhost",
            Port:          5432,
            User:          "postgres",
            Password:      "password",
            Database:      "myapp",
            SSLMode:       "disable",
        }),
    })

    server.Start()
}

func HandleUsers(c *gin.Context, s *EpicServer.Server) {
    db := EpicServerDb.GetPostgresDB(s, "default")
    // Handle request using PostgreSQL...
}

MySQL

package main

import (
    "github.com/tomskip123/EpicServer"
    "github.com/tomskip123/EpicServer/db"
)

func main() {
    server := EpicServer.NewServer([]EpicServer.Option{
        EpicServer.SetSecretKey([]byte("your-secret-key")),
    })

    server.UpdateAppLayer([]EpicServer.AppLayer{
        // Configure MySQL
        EpicServerDb.WithMySQL(EpicServerDb.MySQLConfig{
            ConnectionName: "default",
            Host:          "localhost",
            Port:          3306,
            User:          "root",
            Password:      "password",
            Database:      "myapp",
        }),
    })

    server.Start()
}

func HandleUsers(c *gin.Context, s *EpicServer.Server) {
    db := EpicServerDb.GetMySQLDB(s, "default")
    // Handle request using MySQL...
}

GORM

package main

import (
	"github.com/tomskip123/EpicServer"
	"github.com/tomskip123/EpicServer/db"
)

func main() {
	server := EpicServer.NewServer([]EpicServer.Option{
		EpicServer.SetSecretKey([]byte("your-secret-key")),
	})

	server.UpdateAppLayer([]EpicServer.AppLayer{
		// Configure GORM
		EpicServerDb.WithGorm(&EpicServerDb.GormConfig{
			ConnectionName: "default",
			Dialect:        "mysql", // "mysql", "postgres", or "sqlite"
			DSN:            "user:password@tcp(localhost:3306)/dbname",
		}),
	})

	server.Start()
}

func HandleUsers(c *gin.Context, s *EpicServer.Server) {
	db := EpicServerDb.GetGormDB(s, "default")
	// Handle request using GORM...
}

Caching

EpicServer includes a built-in memory cache system for temporary data storage.

Setting Up Memory Cache

package main

import (
    "github.com/tomskip123/EpicServer"
    "github.com/tomskip123/EpicServer/cache"
)

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Configure memory cache
            EpicServerCache.WithMemoryCache(&EpicServerCache.MemoryCacheConfig{
                Name: "myCache",
                Type: "memory",
            }),
        },
    })

    // Use the cache in your handlers
    cache := EpicServerCache.GetMemoryCache(server, "myCache")
    
    server.Start()
}

Using the Cache

The cache provides simple key-value storage with expiration:

func MyHandler(c *gin.Context) {
    cache := EpicServerCache.GetMemoryCache(server, "myCache")
    
    // Set cache item with 5-minute expiration
    cache.Set("myKey", "myValue", 5*time.Minute)
    
    // Get cache item
    value, exists := cache.Get("myKey")
    if exists {
        // Use cached value
    }
    
    // Delete cache item
    cache.Delete("myKey")
}

Cache Features

  • In-memory key-value storage
  • Automatic expiration of cached items
  • Thread-safe operations
  • Zero configuration required for memory cache
  • Multiple named cache instances

Cache Methods

  • Set(key string, value interface{}, duration time.Duration) - Store a value with expiration
  • Get(key string) (interface{}, bool) - Retrieve a value if it exists
  • Delete(key string) - Remove a value from the cache

Static File Serving

EpicServer provides efficient static file serving with support for embedded files.

Basic Static File Serving

Serve static files from a directory:

//go:embed static/*
var staticFiles embed.FS

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Serve static files
            EpicServer.WithStaticDirectory("/static", &staticFiles, "static"),
        },
    })
}

Custom MIME Types

Serve specific static files with custom MIME types:

//go:embed favicon.ico
var favicon embed.FS

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Serve a single static file
            EpicServer.WithStaticFile(
                "favicon.ico",           // URL path
                &favicon,                // Embedded filesystem
                "favicon.ico",           // File path in embedded filesystem
                "image/x-icon",          // MIME type
            ),
        },
    })
}

SPA (Single Page Application) Support

Configure the server to handle SPA routing:

//go:embed dist/*
var spaFiles embed.FS

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Configure SPA handling
            EpicServer.WithSPACatchAll(
                &spaFiles,              // Embedded filesystem
                "dist",                 // Static files directory
                "dist/index.html",      // SPA entry point
            ),
        },
    })
}

Static File Features

  • Embedded file system support using Go 1.16+ embed package
  • Automatic MIME type detection
  • Custom MIME type configuration
  • SPA route fallback support
  • Directory listing prevention
  • Efficient file serving

Static File Configuration

The static file system supports:

  • Multiple static directories
  • Mixed static files and API routes
  • Custom 404 handling
  • Secure file serving
  • File type restrictions
  • Path normalization

Example with Multiple Static Configurations

//go:embed assets/* spa/* favicon.ico
var files embed.FS

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Serve static assets
            EpicServer.WithStaticDirectory("/assets", &files, "assets"),
            
            // Serve favicon
            EpicServer.WithStaticFile("favicon.ico", &files, "favicon.ico", "image/x-icon"),
            
            // Configure SPA
            EpicServer.WithSPACatchAll(&files, "spa", "spa/index.html"),
        },
    })
}

Middleware

EpicServer provides several built-in middleware options and supports custom middleware creation.

Compression Middleware

Automatically compresses responses and sets appropriate cache headers:

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            EpicServer.WithCompression(),
        },
    })
}

Features:

  • Automatic gzip compression
  • Smart cache control headers
  • Asset-specific caching rules
  • Conditional compression based on Accept-Encoding

CORS Middleware

Configure Cross-Origin Resource Sharing:

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            EpicServer.WithCors([]string{
                "https://example.com",
                "https://api.example.com",
            }),
        },
    })
}

Features:

  • Origin validation
  • Configurable allowed origins
  • Preflight request handling
  • Custom headers support
  • Credential support

CSRF Protection

Enable CSRF token validation:

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            EpicServer.WithCSRFProtection(),
        },
    })
}

// In your handlers
func MyHandler(c *gin.Context) {
    // Generate CSRF token
    token, _ := EpicServer.GenerateCSRFToken()
    
    // Validate token in POST/PUT/DELETE requests
    if !EpicServer.IsTrustedSource(c.Request) {
        // Handle CSRF validation
    }
}

Features:

  • Automatic token generation
  • Token validation
  • Trusted source bypass
  • Custom token storage
  • Header/Form support

WWW Redirect Middleware

Remove 'www' prefix from domains:

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            EpicServer.WithRemoveWWW(),
        },
    })
}

Features:

  • Automatic www detection
  • Permanent redirects (301)
  • HTTPS upgrade support
  • Path preservation

Custom Middleware

Create your own middleware:

func MyCustomMiddleware() EpicServer.AppLayer {
    return func(s *EpicServer.Server) {
        s.Engine.Use(func(c *gin.Context) {
            // Pre-processing
            c.Set("custom_key", "custom_value")
            
            c.Next()
            
            // Post-processing
            status := c.Writer.Status()
            if status >= 500 {
                s.Logger.Error("Server error occurred")
            }
        })
    }
}

// Usage
server := EpicServer.NewServer(&EpicServer.NewServerParam{
    AppLayer: []EpicServer.AppLayer{
        MyCustomMiddleware(),
    },
})

Middleware Order

Middleware is executed in the order it's added:

server := EpicServer.NewServer(&EpicServer.NewServerParam{
    AppLayer: []EpicServer.AppLayer{
        EpicServer.WithCompression(),    // 1st
        EpicServer.WithCors(origins),    // 2nd
        EpicServer.WithRemoveWWW(),      // 3rd
        MyCustomMiddleware(),            // 4th
    },
})

Built-in Security Headers

All responses automatically include security headers:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Strict-Transport-Security: max-age=31536000; includeSubDomains
  • Content-Security-Policy: configurable

Advanced Usage

Custom Configuration

Add your own configuration values:

type MyCustomConfig struct {
    APIKey      string
    MaxRequests int
    Features    []string
}

customConfig := MyCustomConfig{
    APIKey:      "my-api-key",
    MaxRequests: 1000,
    Features:    []string{"feature1", "feature2"},
}

server := EpicServer.NewServer(&EpicServer.NewServerParam{
    Configs: []EpicServer.Option{
        EpicServer.SetCustomConfig(customConfig),
    },
})

// Access custom config in handlers
func MyHandler(c *gin.Context, s *EpicServer.Server) {
    config := EpicServer.GetCustomConfig(s).(MyCustomConfig)
    apiKey := config.APIKey
    // Use configuration...
}

Multiple Database Connections

You can configure multiple database connections with different connection names:

server := EpicServer.NewServer(&EpicServer.NewServerParam{
    AppLayer: []EpicServer.AppLayer{
        // Configure multiple databases
        EpicServerDb.WithMongo(&EpicServerDb.MongoConfig{
            ConnectionName: "users",
            URI:           "mongodb://localhost:27017",
            DatabaseName:  "users",
        }),
        EpicServerDb.WithPostgres(EpicServerDb.PostgresConfig{
            ConnectionName: "products",
            Host:          "localhost",
            Database:      "products",
            // ...other config
        }),
        EpicServerDb.WithMySQL(EpicServerDb.MySQLConfig{
            ConnectionName: "orders",
            Host:          "localhost",
            Database:      "orders",
            // ...other config
        }),
    },
})

Authentication Hooks

Implement custom authentication logic:

type MyAuthHooks struct {
    db *Database
}

func (h *MyAuthHooks) OnUserCreate(user EpicServer.Claims) (string, error) {
    // Create user in database
    return userID, nil
}

func (h *MyAuthHooks) GetUserOrCreate(user EpicServer.Claims) (*EpicServer.CookieContents, error) {
    // Get or create user and return session data
    return &EpicServer.CookieContents{
        UserId:     user.UserID,
        Email:      user.Email,
        SessionId:  generateSessionID(),
        IsLoggedIn: true,
        ExpiresOn:  time.Now().Add(time.Hour * 24),
    }, nil
}

// Add auth hooks to server
server.UpdateAppLayer([]EpicServer.AppLayer{
    EpicServer.WithAuthHooks(&MyAuthHooks{db: db}),
})

Custom Middleware

Create your own middleware:

func MyCustomMiddleware() EpicServer.AppLayer {
    return func(s *EpicServer.Server) {
        s.Engine.Use(func(c *gin.Context) {
            // Pre-processing
            c.Set("custom_key", "custom_value")
            
            c.Next()
            
            // Post-processing
            status := c.Writer.Status()
            if status >= 500 {
                s.Logger.Error("Server error occurred")
            }
        })
    }
}

// Usage
server := EpicServer.NewServer(&EpicServer.NewServerParam{
    AppLayer: []EpicServer.AppLayer{
        MyCustomMiddleware(),
    },
})

SPA Support

Configure the server to handle SPA routing:

 //go:embed dist/*
 var spaFiles embed.FS
 
 func main() {
     server := EpicServer.NewServer([]EpicServer.Option{
         EpicServer.SetSecretKey([]byte("your-secret-key")),
     })
     server.UpdateAppLayer([]EpicServer.AppLayer{
         // Configure SPA handling
         EpicServer.WithSPACatchAll(
             &spaFiles,              // Embedded filesystem
             "dist",                 // Static files directory
             "dist/index.html",      // SPA entry point
         ),
     })
 }

Security

Authentication Setup

package main

import (
    "github.com/tomskip123/EpicServer"
)

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            // Configure authentication
            EpicServer.WithAuth([]EpicServer.Provider{
                {
                    Name:         "google",
                    ClientId:     "your-client-id",
                    ClientSecret: "your-client-secret",
                    Callback:     "http://localhost:3000/auth/google/callback",
                },
            }, &EpicServer.SessionConfig{
                CookieName:      "auth_session",
                CookieDomain:    "localhost",
                CookieSecure:    false,
                CookieHTTPOnly:  true,
                SessionDuration: time.Hour * 24,
            }),
            // Add authentication middleware
            EpicServer.WithAuthMiddleware(EpicServer.SessionConfig{
                CookieName:   "auth_session",
                CookieDomain: "localhost",
                CookieSecure: false,
            }),
        },
    })

    server.Start()
}

CSRF Protection

Enable CSRF token validation:

func main() {
    server := EpicServer.NewServer(&EpicServer.NewServerParam{
        AppLayer: []EpicServer.AppLayer{
            EpicServer.WithCSRFProtection(),
        },
    })
}

// In your handlers
func MyHandler(c *gin.Context) {
    // Generate CSRF token
    token, _ := EpicServer.GenerateCSRFToken()
    
    // Validate token in POST/PUT/DELETE requests
    if !EpicServer.IsTrustedSource(c.Request) {
        // Handle CSRF validation
    }
}

Security Headers

All responses automatically include security headers:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Strict-Transport-Security: max-age=31536000; includeSubDomains
  • Content-Security-Policy: configurable

Environment Variables

Required environment variables for secure authentication:

SECURE_COOKIE_HASH_KEY=base64_encoded_32_byte_key
SECURE_COOKIE_BLOCK_KEY=base64_encoded_32_byte_key
ENCRYPTION_KEY=32_byte_hex_encoded_key

Generate secure keys using:

hashKey, _ := EpicServer.GenerateEncryptionKey()
blockKey, _ := EpicServer.GenerateEncryptionKey()

API Reference

Server Options

  • WithHealthCheck(path string) - Adds a health check endpoint
  • WithCompression() - Enables response compression
  • WithRemoveWWW() - Removes www prefix from domain
  • WithCors(origins []string) - Configures CORS settings
  • WithEnvironment(environment string) - Sets runtime environment (development/production/test)
  • WithTrustedProxies(proxies []string) - Configures trusted proxy addresses
  • WithHttp2() - Enables HTTP/2 support

Database Methods

MongoDB specific helpers:

  • StringToObjectID(id string) - Convert string to MongoDB ObjectID
  • StringArrayToObjectIDArray(ids []string) - Convert string array to ObjectID array
  • UpdateIndexes(ctx, collection, indexes) - Create or update collection indexes
  • StringArrayContains(array []string, value string) - Check if string array contains value

GORM specific helpers:

  • AutoMigrateModels(s *EpicServer.Server, connectionName string, models ...interface{}) error - Run GORM AutoMigrate for the given models

Cache Methods

  • Set(key string, value interface{}, duration time.Duration) - Store a value with expiration
  • Get(key string) (interface{}, bool) - Retrieve a value if it exists
  • Delete(key string) - Remove a value from the cache

Authentication Methods

  • GenerateCSRFToken() (string, error) - Generate a CSRF token
  • IsTrustedSource(req *http.Request) bool - Validate CSRF token
  • GetSession(c *gin.Context) (*Session, error) - Retrieve session data

Contributing

Getting Started

  1. Fork the repository
  2. Clone your fork:
git clone https://github.com/yourusername/EpicServer.git
  1. Create your feature branch:
git checkout -b feature/amazing-feature

Development

  1. Ensure you have Go 1.16+ installed
  2. Run tests before making changes:
go test -v ./...

Testing Your Changes

The project includes tests for core functionality. Always run tests before submitting a PR:

# Run all tests
go test -v ./...

# Run specific tests (examples)
go test -run TestVerifyCSRFToken     # Test CSRF middleware
go test -run TestCompressMiddleware  # Test compression
go test -run TestServer_Start       # Test server startup

Key areas covered by tests:

  • Server initialization and configuration
  • Built-in middleware (CSRF, Compression, CORS, WWW redirect)
  • Environment settings
  • Server lifecycle
  • Logger functionality

Submitting Changes

  1. Commit your changes:
git commit -m 'Add some amazing feature'
  1. Push to your fork:
git push origin feature/amazing-feature
  1. Open a Pull Request

Code Style

  • Follow standard Go formatting (go fmt)
  • Add tests for new features
  • Update documentation as needed
  • Keep commits focused and atomic

License

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

Support

Project Link: https://github.com/tomskip123/EpicServer

About

EpicServer is a library on top of Go Gin that provides helpful methods for, Middleware, Authentication, OAuth provider setup and exposes hooks to customise behaivour.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages