gx

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

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

Go to latest
Published: Apr 18, 2026 License: MIT Imports: 18 Imported by: 0

README

GX - Go Web Framework

Version: 0.1.0-alpha
Status: Active Development
Go Version: 1.22+

GX is a modern, high-performance web framework for Go that combines Express.js-like simplicity with Go's type safety and performance.

Philosophy

  1. Explicit over Magic - No hidden behaviors, no reflection at runtime
  2. Composable over Monolithic - Independent, testable components
  3. Framework Works, Developer Expresses - Automation through correct declarations

Core Features

✓ Implemented (Core Layer)
  • Response Interface - Chainable, immutable response builders
  • Context with Pooling - Zero-allocation request context via sync.Pool
  • Radix-Tree Router - O(log n) route lookups with conflict detection at boot
  • Middleware System - Unique design where middleware can observe and modify responses
  • Route Groups - Nested routing with scoped middleware
  • Server-Sent Events - First-class SSE support
  • TLS Utilities - Auto-generated self-signed certificates for development
  • Graceful Shutdown - Clean shutdown with configurable timeouts
🚧 Planned (GX Layer)
  • Contract & Schema system
  • Error taxonomy
  • Plugin system
  • OpenAPI generation
  • Observability (tracing, metrics, structured logging)
  • Lifecycle hooks
  • HTTP/3 support

Installation

go get github.com/s-anzie/gx

Quick Start

package main

import (
    "github.com/s-anzie/gx/core"
    "log"
)

func main() {
    app := core.New()

    app.GET("/", func(c *core.Context) core.Response {
        return c.JSON(map[string]string{
            "message": "Hello, GX!",
        })
    })

    log.Fatal(app.Listen(":8080"))
}

Core Concepts

Handler Signature

The fundamental decision of GX: handlers return Response values.

type Handler func(*Context) Response

Why this matters:

  • ✓ Compiler-enforced - forgetting return is a compile error
  • ✓ Testable without HTTP - unit test handlers directly
  • ✓ Unified error handling - errors are responses, not separate code paths

Compare with other frameworks:

Framework Signature Problem
Gin func(*Context) Forgot return? Silent bug
Echo func(*Context) error Error vs response = two code paths
GX func(*Context) Response Unified, testable, enforced ✓
Context

Pooled request context with rich API:

func handler(c *core.Context) core.Response {
    // Routing
    id := c.Param("id")
    page := c.QueryDefault("page", "1")
    
    // Request body
    var data MyStruct
    c.BindJSON(&data)
    
    // Headers & metadata
    token := c.Header("Authorization")
    ip := c.ClientIP()
    
    // Protocol detection
    if c.IsHTTP2() {
        // handle HTTP/2
    }
    
    // Store per-request values
    c.Set("user", user)
    
    return c.JSON(data)
}
Middleware

Unlike Express, GX middleware receives the response from the next handler:

func timer(c *core.Context, next core.Handler) core.Response {
    start := time.Now()
    
    res := next(c)  // handler executes here
    
    // After - full access to the Response
    duration := time.Since(start)
    return core.WithHeader(res, "X-Duration", duration.String())
}

This is structurally impossible in Express where next() is fire-and-forget.

Responses

All response types are chainable and immutable:

// JSON response
return c.JSON(user)

// with custom status and headers
return c.JSON(user).
    Status(201).
    Header("Location", "/users/"+user.ID).
    Cache(5 * time.Minute)

// Text response
return c.Text("Hello, %s!", name)

// HTML response
return c.HTML("<h1>Welcome</h1>")

// File response
return c.File("/path/to/file.pdf")

// Stream response
return c.Stream("video/mp4", videoReader)

// Redirect
return c.Redirect("/login").Permanent()

// No content
return c.NoContent()
Router

Radix-tree with deterministic conflict resolution:

app := core.New()

// Static routes
app.GET("/users/me", getCurrentUser)

// Parameters
app.GET("/users/:id", getUser)

// Wildcards
app.GET("/files/*path", serveFile)

Priority: static > parameter > wildcard

Conflicts detected at boot time, not runtime:

app.GET("/users/:id", handler1)
app.GET("/users/:uid", handler2)  // PANIC: conflicting param names
Groups

Organize routes with shared prefixes and middleware:

api := app.Group("/api/v1")
api.Use(auth, rateLimit)

users := api.Group("/users")
users.GET("", listUsers)           // GET /api/v1/users
users.GET("/:id", getUser)         // GET /api/v1/users/:id
users.POST("", createUser)         // POST /api/v1/users
users.PATCH("/:id", updateUser)    // PATCH /api/v1/users/:id
users.DELETE("/:id", deleteUser)   // DELETE /api/v1/users/:id
Server-Sent Events

First-class SSE support:

app.GET("/events", func(c *core.Context) core.Response {
    return core.SSE(func(stream *core.SSEStream) error {
        ticker := time.NewTicker(1 * time.Second)
        defer ticker.Stop()
        
        for {
            select {
            case <-stream.Context().Done():
                return nil
            case t := <-ticker.C:
                stream.Send(core.SSEEvent{
                    Event: "time",
                    Data:  t.Format(time.RFC3339),
                })
            }
        }
    })
})
TLS

Development TLS made easy:

app := core.New()

// Auto-generate self-signed certificate
app.WithDevTLS("localhost", "127.0.0.1")

app.Listen(":8443")  // HTTPS enabled

Or use your own certificates:

app.WithTLS("cert.pem", "key.pem")
Graceful Shutdown

Built-in support for clean shutdowns:

app := core.New()

// ... register routes ...

// Handles SIGTERM/SIGINT automatically
log.Fatal(app.ListenWithGracefulShutdown(":8080"))

Examples

See the examples/ directory:

Run an example:

go run examples/basic/main.go

Architecture

┌──────────────────────────────────────┐
│         Application Code             │
├──────────────────────────────────────┤
│         GX Layer (planned)           │
│  Contracts · Schema · Errors         │
│  Plugins · Observability             │
├──────────────────────────────────────┤
│         Core Layer (✓)               │
│  Router · Context · Response         │
│  Middleware · Groups · SSE           │
├──────────────┬───────────────────────┤
│  net/http    │  (Future: HTTP/2)     │
└──────────────┴───────────────────────┘

Performance

  • Zero allocations on hot path via context pooling
  • O(log n) route lookups with radix-tree
  • No reflection at request time
  • Deterministic - conflicts detected at boot, not runtime

Roadmap

Phase 1: Core (Current)
  • Response system
  • Context & pooling
  • Router with radix-tree
  • Middleware
  • Groups
  • SSE
  • TLS utilities
Phase 2: GX Layer (Next)
  • Contract & Schema system
  • Error taxonomy
  • Plugin architecture
  • OpenAPI generation
  • Validation
Phase 3: Observability
  • Structured logging
  • Tracing (OpenTelemetry)
  • Metrics (Prometheus)
Phase 4: Advanced
  • HTTP/3 support
  • WebSocket channels
  • QUIC primitives

Design Principles

Handler Return Values
// ✓ Good - explicit return, testable
func getUser(c *core.Context) core.Response {
    return c.JSON(user)
}

// ✗ Bad (other frameworks) - side effect, easy to forget return
func getUser(c SomeContext) {
    c.JSON(user)  // forgot return? double send!
}
Middleware & Response Access
// GX - middleware sees the response
func log(c *core.Context, next core.Handler) core.Response {
    res := next(c)
    log.Printf("Status: %d", res.Status())  // ✓ can observe
    return res
}

// Express - fire and forget
function log(req, res, next) {
    next()  // can't see what happened after
}
Error Handling

In GX, errors ARE responses:

// Unified path
if err != nil {
    return c.Fail(ErrNotFound)  // returns Response
}
return c.JSON(data)  // also returns Response

No special error handling, no double code paths.

Testing

Handlers are pure functions - easy to test:

func TestGetUser(t *testing.T) {
    c := makeMockContext("id", "123")
    
    res := getUser(c)
    
    assert.Equal(t, 200, res.Status())
    // no HTTP server needed!
}

Contributing

GX is in active development. Contributions welcome!

  1. Read the design specs
  2. Fork and create a feature branch
  3. Ensure tests pass
  4. Submit a PR

License

MIT License - see LICENSE

Credits

Inspired by:

  • Express.js - minimalism and developer experience
  • Gin - performance focus
  • Echo - clean API design
  • But taking full advantage of Go's strengths

Status: Core layer complete, GX layer in progress.
Next: Contract system, Error taxonomy, Plugin architecture

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// 4xx Client Errors
	ErrBadRequest          = E(400, "BAD_REQUEST", "The request could not be understood")
	ErrUnauthorized        = E(401, "UNAUTHORIZED", "Authentication is required")
	ErrForbidden           = E(403, "FORBIDDEN", "You don't have permission to access this resource")
	ErrNotFound            = E(404, "NOT_FOUND", "The requested resource was not found")
	ErrMethodNotAllowed    = E(405, "METHOD_NOT_ALLOWED", "The HTTP method is not allowed for this resource")
	ErrConflict            = E(409, "CONFLICT", "The request conflicts with the current state")
	ErrGone                = E(410, "GONE", "The resource is no longer available")
	ErrPayloadTooLarge     = E(413, "PAYLOAD_TOO_LARGE", "The request payload is too large")
	ErrUnsupportedMedia    = E(415, "UNSUPPORTED_MEDIA_TYPE", "The media type is not supported")
	ErrUnprocessableEntity = E(422, "UNPROCESSABLE_ENTITY", "The request was well-formed but contains semantic errors")
	ErrTooManyRequests     = E(429, "TOO_MANY_REQUESTS", "Too many requests, please slow down")

	// 5xx Server Errors
	ErrInternal           = E(500, "INTERNAL_ERROR", "An internal server error occurred")
	ErrNotImplemented     = E(501, "NOT_IMPLEMENTED", "This feature is not implemented")
	ErrBadGateway         = E(502, "BAD_GATEWAY", "Invalid response from upstream server")
	ErrServiceUnavailable = E(503, "SERVICE_UNAVAILABLE", "The service is temporarily unavailable")
	ErrGatewayTimeout     = E(504, "GATEWAY_TIMEOUT", "Upstream server timed out")

	// Validation Error (special case with field details)
	ErrValidation = E(422, "VALIDATION_ERROR", "Request validation failed")
)

Functions

func Go

func Go(fn func())

Go runs fn in a new goroutine with panic recovery. A panic in fn is caught, logged as an error with a stack trace, and the server continues operating normally.

Always prefer gx.Go over bare `go func()` in handlers. Never store *gx.Context or *core.Context in the goroutine — extract needed values before launching.

id := c.Param("id")
gx.Go(func() {
    sendEmail(id)
})

func GoCtx

func GoCtx(ctx context.Context, fn func(context.Context))

GoCtx runs fn in a new goroutine with context propagation and panic recovery. Use this when the goroutine needs to respect request cancellation.

ctx := c.GoContext()
gx.GoCtx(ctx, func(ctx context.Context) {
    doAsyncWork(ctx)
})

func LoadConfig

func LoadConfig[T any]() (T, error)

LoadConfig loads application configuration from environment variables using struct field tags:

  • `env:"VAR_NAME"` — variable name to read

  • `default:"value"` — fallback when env var is absent

  • `required:"true"` — returns an error if env var is absent

    type AppConfig struct { DatabaseURL string `env:"DATABASE_URL" required:"true"` RedisURL string `env:"REDIS_URL" default:"redis://localhost:6379"` Port int `env:"PORT" default:"8080"` }

    cfg, err := gx.LoadConfig[AppConfig]()

func RegisterValidator

func RegisterValidator(tag string, fn validator.Func)

RegisterValidator registers a custom validation rule, available globally. Must be called before the first use of Validate/ValidateOrFail.

gx.RegisterValidator("slug", func(fl validator.FieldLevel) bool {
    return slugRegex.MatchString(fl.Field().String())
})

func RegisterValidatorAlias

func RegisterValidatorAlias(alias, tags string)

RegisterValidatorAlias registers a mapping from a custom tag to an existing combination of tags.

gx.RegisterValidatorAlias("password", "required,min=8,max=72")

func SetTyped

func SetTyped[T any](c *core.Context, value *T)

SetTyped stores a value in the context using its type name as the key This is the counterpart to Typed/TryTyped - middleware and validators use this

func TryTyped

func TryTyped[T any](c *core.Context) (*T, bool)

TryTyped retrieves a value from the context store and casts it to type T Returns (value, true) if found and castable, (nil, false) otherwise Use this when the value might not be present (e.g., optional middleware data)

func Typed

func Typed[T any](c *core.Context) *T

Typed retrieves a value from the context store and casts it to type T Panics if the value doesn't exist or cannot be cast to T This is intended for use in handlers where the Contract has validated the presence

func Validate

func Validate(v any) error

Validate validates a struct against its `validate` tags. Returns nil if valid, or a ValidationError with field-level details.

if err := gx.Validate(req); err != nil {
    return c.Fail(gx.ErrValidation).With("fields", err)
}

func ValidateOrFail

func ValidateOrFail(c *core.Context, v any) (core.Response, bool)

ValidateOrFail validates v and returns (response, false) with a 422 error body if validation fails. Returns (nil, true) if valid.

if res, ok := gx.ValidateOrFail(c, &req); !ok {
    return res
}

func ValidateVar

func ValidateVar(v any, tag string) error

ValidateVar validates a single value against a tag string.

if err := gx.ValidateVar(email, "required,email"); err != nil {
    return c.Fail(ErrInvalidEmail)
}

Types

type App

type App struct {
	*core.App
	// contains filtered or unexported fields
}

App is the GX application instance that extends core.App

func New

func New(opts ...Option) *App

New creates a new GX application with the given options

func (*App) Boot

func (app *App) Boot(ctx context.Context) error

Boot executes all boot hooks in order

func (*App) Channel

func (app *App) Channel(path string, contract ChannelContract, handler ChannelHandler)

Channel registers a bidirectional channel endpoint The actual transport (WebSocket or QUIC) is chosen based on the client's protocol

func (*App) DELETE

func (app *App) DELETE(path string, contractOrHandler any, handlers ...any)

DELETE registers a DELETE route with optional contract

func (*App) Environment

func (app *App) Environment() Environment

Environment returns the current application environment

func (*App) GET

func (app *App) GET(path string, contractOrHandler any, handlers ...any)

GET registers a GET route with optional contract

func (*App) GenerateOpenAPI

func (app *App) GenerateOpenAPI(title, version string) OpenAPISpec

GenerateOpenAPI creates an OpenAPI specification Full implementation will be added with the OpenAPI plugin

func (*App) GetContracts

func (app *App) GetContracts() []RouteContract

GetContracts returns all registered contracts

func (*App) Group

func (app *App) Group(prefix string, middlewares ...Middleware) *Group

Group creates a new GX route group.

func (*App) HEAD

func (app *App) HEAD(path string, contractOrHandler any, handlers ...any)

HEAD registers a HEAD route.

func (*App) Health

func (app *App) Health(name string, check func(context.Context) error, opts ...HealthCheckOption)

Health registers a health check for a dependency

func (*App) Install

func (app *App) Install(plugin Plugin, opts ...PluginInstallOption) *App

Install adds a plugin to the application with optional install options.

app.Install(auth.New())
app.Install(recovery.New(), gx.PluginPriority(1000))  // execute first

func (*App) IsDevelopment

func (app *App) IsDevelopment() bool

IsDevelopment returns true if the app is in development mode

func (*App) IsProduction

func (app *App) IsProduction() bool

IsProduction returns true if the app is in production mode

func (*App) Listen

func (app *App) Listen(addr string, opts ...core.ListenOption) error

Listen starts the server and ensures plugin middlewares are registered before serving requests. This overrides core.App.Listen() to guarantee that RequestPlugin middlewares are set up.

func (*App) ListenHTTPRedirect

func (a *App) ListenHTTPRedirect(httpAddr, httpsAddr string)

ListenHTTPRedirect starts a dedicated HTTP server on httpAddr that permanently redirects all requests to the corresponding HTTPS URL on httpsAddr. It runs in a background goroutine and returns immediately.

app.ListenHTTPRedirect(":80", ":443")

func (*App) Logger

func (app *App) Logger() Logger

Logger returns the app's logger

func (*App) Metrics

func (app *App) Metrics() MetricsRegistry

Metrics returns the app's metrics registry

func (*App) OPTIONS

func (app *App) OPTIONS(path string, contractOrHandler any, handlers ...any)

OPTIONS registers an OPTIONS route.

func (*App) OnBoot

func (app *App) OnBoot(hook BootHook)

OnBoot registers a hook to be called during application boot

func (*App) OnMigrate

func (app *App) OnMigrate(callback func(MigrateEvent))

OnMigrate registers a callback for QUIC connection migration events Called when a client changes network (e.g., WiFi → 4G)

func (*App) OnShutdown

func (app *App) OnShutdown(hook ShutdownHook)

OnShutdown registers a hook to be called during application shutdown

func (*App) PATCH

func (app *App) PATCH(path string, contractOrHandler any, handlers ...any)

PATCH registers a PATCH route with optional contract

func (*App) POST

func (app *App) POST(path string, contractOrHandler any, handlers ...any)

POST registers a POST route with optional contract

func (*App) PUT

func (app *App) PUT(path string, contractOrHandler any, handlers ...any)

PUT registers a PUT route with optional contract

func (*App) RegisterHealthEndpoints

func (app *App) RegisterHealthEndpoints()

RegisterHealthEndpoints adds health check endpoints to the app

func (*App) ServeHTTP

func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler, ensuring plugin middlewares are registered in priority order before the first request is processed.

func (*App) ShutdownGracefully

func (app *App) ShutdownGracefully(ctx context.Context) error

ShutdownGracefully executes all shutdown hooks in reverse order

func (*App) StartHealthChecks

func (app *App) StartHealthChecks(ctx context.Context)

StartHealthChecks begins periodic health check execution

func (*App) Tracer

func (app *App) Tracer() Tracer

Tracer returns the app's tracer

type AppError

type AppError struct {
	Status  int            `json:"status"`
	Code    string         `json:"code"`
	Message string         `json:"message"`
	Details map[string]any `json:"details,omitempty"`
	// contains filtered or unexported fields
}

AppError represents a structured application error

func E

func E(status int, code, message string, translations ...Translations) AppError

E creates a new AppError - shorthand constructor. An optional Translations map can be provided as the fourth argument:

var ErrNotFound = gx.E(404, "NOT_FOUND", "Resource not found", gx.Translations{
    "fr": "Ressource introuvable",
    "es": "Recurso no encontrado",
})

func ValidationError

func ValidationError(fields ...FieldError) AppError

ValidationError creates a validation error with field-level details

func (AppError) Error

func (e AppError) Error() string

Error implements the error interface

func (AppError) MessageFor

func (e AppError) MessageFor(lang string) string

MessageFor returns the translated message for lang, falling back to the default English message if no translation is available.

func (AppError) ToResponse

func (e AppError) ToResponse() core.Response

ToResponse converts the error to a core.Response

func (AppError) Unwrap

func (e AppError) Unwrap() error

Unwrap returns the wrapped error for errors.Is/As compatibility

func (AppError) With

func (e AppError) With(key string, value any) AppError

With adds contextual details to the error Returns a new error instance (immutable pattern)

func (AppError) Wrap

func (e AppError) Wrap(err error) AppError

Wrap wraps an internal error (logged but not exposed to client)

type BootHook

type BootHook func(context.Context) error

BootHook is a function called during application boot

type Channel

type Channel interface {
	// Send serializes and sends a value (JSON by default)
	Send(v any) error

	// Receive deserializes the next message into v
	Receive(v any) error

	// SendRaw sends raw bytes
	SendRaw(b []byte) error

	// ReceiveRaw receives the next raw message
	ReceiveRaw() ([]byte, error)

	// Done returns a channel that's closed when the client disconnects
	Done() <-chan struct{}

	// Proto returns the protocol actually used ("websocket" or "quic")
	Proto() string

	// Close closes the channel
	Close() error
}

Channel is the interface for bidirectional real-time communication It abstracts WebSocket (HTTP/1.1, HTTP/2) and QUIC streams (HTTP/3)

func NewNoopChannel

func NewNoopChannel() Channel

NewNoopChannel creates a new no-op channel for testing

type ChannelContract

type ChannelContract struct {
	Summary     string
	Description string
	Tags        []string

	// Message schemas
	InputMessage  SchemaRef // Messages from client to server
	OutputMessage SchemaRef // Messages from server to client

	// Possible errors
	Errors []AppError
}

ChannelContract describes a channel endpoint's schema

type ChannelHandler

type ChannelHandler func(*Context, Channel) error

ChannelHandler is a handler function for channel-based endpoints It receives both the request context and the bidirectional channel

type ChannelRoute

type ChannelRoute struct {
	Path     string
	Contract ChannelContract
	Handler  ChannelHandler
}

ChannelRoute represents a registered channel endpoint

type Context

type Context struct {
	*core.Context
	// contains filtered or unexported fields
}

Context extends core.Context with GX-specific functionality

func (*Context) Fail

func (c *Context) Fail(err AppError) Response

Fail creates an error response from an AppError

func (*Context) Log

func (c *Context) Log() Logger

Log returns a logger correlated with the current request The logger includes trace ID, span ID, request ID, route, and method

func (*Context) SSEChannel

func (c *Context) SSEChannel() (Channel, error)

SSEChannel creates a server-to-client channel using Server-Sent Events This is a simpler alternative for use cases that don't need client→server messages

func (*Context) Span

func (c *Context) Span() Span

Span returns the current request's span Returns a no-op span if tracing is not enabled

func (*Context) Trace

func (c *Context) Trace(name string) Span

Trace creates a new child span with the given name

func (*Context) ValidateOrFail

func (c *Context) ValidateOrFail(v any) (Response, bool)

ValidateOrFail validates v and returns (response, false) with a 422 error body if validation fails. Returns (nil, true) if valid.

if res, ok := c.ValidateOrFail(&req); !ok {
    return res
}

type Contract

type Contract struct {
	Summary     string
	Description string
	Tags        []string
	Deprecated  bool

	// Input schemas
	Params SchemaRef // Path parameters
	Query  SchemaRef // Query string
	Body   SchemaRef // Request body

	// Output schema
	Output SchemaRef

	// Possible errors
	Errors []AppError
}

Contract describes what an endpoint accepts and returns

type CoreContext

type CoreContext = core.Context

type CoreHandler

type CoreHandler = core.Handler

type Counter

type Counter interface {
	// Inc increments the counter by 1
	Inc()

	// Add increments the counter by the given value
	Add(value float64)

	// With returns a counter with the given label values
	With(labelValues ...string) Counter
}

Counter is a monotonically increasing metric

type Environment

type Environment string

Environment represents the application environment

const (
	Development Environment = "development"
	Staging     Environment = "staging"
	Production  Environment = "production"
)

type ErrorPlugin

type ErrorPlugin interface {
	Plugin

	// OnError is called when an error occurs
	// Return nil to let the next error handler process it
	// Return a Response to handle the error and stop propagation
	OnError(c *Context, err AppError) Response
}

ErrorPlugin is an optional interface for plugins that want to handle errors

type FieldError

type FieldError struct {
	Field   string `json:"field"`
	Rule    string `json:"rule"`
	Message string `json:"message"`
}

FieldError represents a single field validation error

type Gauge

type Gauge interface {
	// Set sets the gauge to the given value
	Set(value float64)

	// Inc increments the gauge by 1
	Inc()

	// Dec decrements the gauge by 1
	Dec()

	// Add adds the given value to the gauge
	Add(value float64)

	// Sub subtracts the given value from the gauge
	Sub(value float64)

	// With returns a gauge with the given label values
	With(labelValues ...string) Gauge
}

Gauge is a metric that can go up and down

type Group

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

Group is the GX route group abstraction. It hides core.Group from application code while delegating to the core router.

func (*Group) Any

func (g *Group) Any(path string, handler any, handlers ...any)

Any registers all HTTP methods with a GX handler.

func (*Group) DELETE

func (g *Group) DELETE(path string, handler any, handlers ...any)

DELETE registers a DELETE route with a GX handler.

func (*Group) GET

func (g *Group) GET(path string, handler any, handlers ...any)

GET registers a GET route with a GX handler.

func (*Group) Group

func (g *Group) Group(prefix string, middlewares ...Middleware) *Group

Group creates a nested GX group.

func (*Group) HEAD

func (g *Group) HEAD(path string, handler any, handlers ...any)

HEAD registers a HEAD route with a GX handler.

func (*Group) OPTIONS

func (g *Group) OPTIONS(path string, handler any, handlers ...any)

OPTIONS registers an OPTIONS route with a GX handler.

func (*Group) PATCH

func (g *Group) PATCH(path string, handler any, handlers ...any)

PATCH registers a PATCH route with a GX handler.

func (*Group) POST

func (g *Group) POST(path string, handler any, handlers ...any)

POST registers a POST route with a GX handler.

func (*Group) PUT

func (g *Group) PUT(path string, handler any, handlers ...any)

PUT registers a PUT route with a GX handler.

func (*Group) Use

func (g *Group) Use(middlewares ...Middleware)

Use adds middleware to the group.

type Handler

type Handler func(*Context) Response

Handler is the GX handler signature (uses gx.Context instead of core.Context)

func WithContract

func WithContract(contract Contract, handler Handler) Handler

WithContract wraps a GX handler with contract validation middleware.

type HealthCheck

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

HealthCheck represents a health check for a dependency

type HealthCheckOption

type HealthCheckOption func(*HealthCheck)

HealthCheckOption configures a health check

func HealthCritical

func HealthCritical(critical bool) HealthCheckOption

HealthCritical marks the check as critical (default: true) Non-critical checks don't fail the /health/ready endpoint

func HealthInterval

func HealthInterval(interval time.Duration) HealthCheckOption

HealthInterval sets the check interval (default: 30s)

func HealthTimeout

func HealthTimeout(timeout time.Duration) HealthCheckOption

HealthTimeout sets the check timeout (default: 5s)

type HealthResponse

type HealthResponse struct {
	Status HealthStatus            `json:"status"`
	Checks map[string]HealthResult `json:"checks,omitempty"`
}

HealthResponse is the JSON response for health endpoints

type HealthResult

type HealthResult struct {
	Status    HealthStatus `json:"status"`
	LatencyMs int64        `json:"latency_ms,omitempty"`
	Error     string       `json:"error,omitempty"`
	LastCheck time.Time    `json:"last_check,omitempty"`
}

HealthResult represents the result of a health check

type HealthStatus

type HealthStatus string

HealthStatus represents the health status of a dependency

const (
	StatusOK       HealthStatus = "ok"
	StatusDegraded HealthStatus = "degraded"
	StatusDown     HealthStatus = "down"
)

type Histogram

type Histogram interface {
	// Observe adds a single observation
	Observe(value float64)

	// With returns a histogram with the given label values
	With(labelValues ...string) Histogram
}

Histogram observes values and counts them in buckets

type LogFormat

type LogFormat string

LogFormat defines the log output format

const (
	LogText LogFormat = "text"
	LogJSON LogFormat = "json"
)

type LogOption

type LogOption func(*logConfig)

func LogLevel

func LogLevel(level slog.Level) LogOption

LogLevel sets the minimum log level

func LogOutput

func LogOutput(output *os.File) LogOption

LogOutput sets the log output destination

func WithLogFormat

func WithLogFormat(format LogFormat) LogOption

WithLogFormat sets the log output format (text or JSON)

type Logger

type Logger interface {
	// Info logs an informational message
	Info(msg string, args ...any)

	// Warn logs a warning message
	Warn(msg string, args ...any)

	// Error logs an error message
	Error(msg string, args ...any)

	// Debug logs a debug message
	Debug(msg string, args ...any)

	// With returns a logger with the given attributes pre-populated
	With(args ...any) Logger
}

Logger is a structured logger interface

type MetricsOption

type MetricsOption func(*metricsConfig)

func MetricsBuckets

func MetricsBuckets(buckets []float64) MetricsOption

MetricsBuckets sets custom histogram buckets

func PrometheusExporter

func PrometheusExporter(addr string) MetricsOption

PrometheusExporter sets the Prometheus metrics endpoint address

type MetricsRegistry

type MetricsRegistry interface {
	// Counter creates or retrieves a counter
	Counter(name, help string, labels ...string) Counter

	// Histogram creates or retrieves a histogram
	Histogram(name, help string, labels ...string) Histogram

	// Gauge creates or retrieves a gauge
	Gauge(name, help string, labels ...string) Gauge
}

MetricsRegistry manages all metrics

type Middleware

type Middleware = core.Middleware

func HTTPSRedirect

func HTTPSRedirect() Middleware

HTTPSRedirect returns a middleware that redirects all HTTP requests to HTTPS using 308 Permanent Redirect (preserves HTTP method, unlike 301). It also sets the HSTS header on responses.

type MigrateEvent

type MigrateEvent struct {
	OldAddr   string
	NewAddr   string
	SessionID string
}

MigrateEvent represents a QUIC connection migration event

type OpenAPIInfo

type OpenAPIInfo struct {
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
	Version     string `json:"version"`
}

type OpenAPISpec

type OpenAPISpec struct {
	OpenAPI string                 `json:"openapi"`
	Info    OpenAPIInfo            `json:"info"`
	Paths   map[string]interface{} `json:"paths,omitempty"`
}

OpenAPISpec generates an OpenAPI 3.1 specification from registered contracts This is a placeholder for future implementation

type Option

type Option func(*App)

Option is a functional option for configuring the GX App

func IgnoreEnv

func IgnoreEnv() Option

IgnoreEnv disables reading of GX_* environment variables. When set, only explicit Go options determine the configuration.

func MaxBodySize

func MaxBodySize(size int64) Option

MaxBodySize sets the maximum allowed size for request bodies

func ReadTimeout

func ReadTimeout(timeout time.Duration) Option

ReadTimeout sets the maximum duration for reading the entire request

func ShutdownTimeout

func ShutdownTimeout(timeout time.Duration) Option

ShutdownTimeout sets the maximum duration for graceful shutdown

func TrustedProxies

func TrustedProxies(proxies ...string) Option

TrustedProxies sets the list of trusted proxy IP addresses/CIDR ranges

func WithDevTLS

func WithDevTLS(hosts ...string) Option

WithDevTLS configures development TLS with self-signed certificate

func WithEnvironment

func WithEnvironment(env Environment) Option

WithEnvironment sets the application environment

func WithHTTP2

func WithHTTP2() Option

WithHTTP2 enables HTTP/2 support (enabled by default with TLS)

func WithHTTP3

func WithHTTP3() Option

WithHTTP3 enables HTTP/3 support (QUIC)

func WithMetrics

func WithMetrics(opts ...MetricsOption) Option

WithMetrics enables Prometheus metrics

func WithStructuredLogs

func WithStructuredLogs(opts ...LogOption) Option

WithStructuredLogs enables structured logging

func WithTLS

func WithTLS(certFile, keyFile string) Option

WithTLS configures TLS using certificate and key files

func WithTracing

func WithTracing(serviceName string, opts ...TracingOption) Option

WithTracing enables distributed tracing with OpenTelemetry

func WriteTimeout

func WriteTimeout(timeout time.Duration) Option

WriteTimeout sets the maximum duration before timing out writes of the response

type Plugin

type Plugin interface {
	// Name returns the unique name of the plugin
	Name() string

	// OnBoot is called during application boot, before the server starts
	OnBoot(app *App) error

	// OnShutdown is called during graceful shutdown
	OnShutdown(ctx context.Context) error
}

Plugin is the base interface for all GX plugins

type PluginInstallOption

type PluginInstallOption func(*pluginEntry)

PluginInstallOption configures how a plugin is installed.

func PluginPriority

func PluginPriority(n int) PluginInstallOption

PluginPriority sets the execution priority for a plugin. Higher values execute earlier (first in the OnRequest chain). Default priority is 0 (last custom plugin).

Standard framework plugin priorities:

recovery:    1000
requestid:    950
logger:       900
cors:         850
ratelimit:    800
auth:         750
cache:        700
compress:     100

type RequestPlugin

type RequestPlugin interface {
	Plugin

	// OnRequest is called for each incoming request
	// It can act as middleware by calling next and potentially modifying the response
	OnRequest(c *Context, next core.Handler) Response
}

RequestPlugin is an optional interface for plugins that need to intercept requests

type Response

type Response = core.Response

Public type aliases for easier API usage

type RouteContract

type RouteContract struct {
	Method   string
	Path     string
	Contract Contract
}

RouteContract stores a route with its contract

type RouteInfo

type RouteInfo struct {
	Method  string
	Path    string
	Handler core.Handler
	Tags    []string
}

RouteInfo contains metadata about a registered route

type RoutePlugin

type RoutePlugin interface {
	Plugin

	// OnRoute is called once for each route registered during boot
	OnRoute(route RouteInfo)
}

RoutePlugin is an optional interface for plugins that need to know about registered routes

type Router

type Router = core.Router

type SchemaRef

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

SchemaRef is a reference to a type schema

func Schema

func Schema[T any]() SchemaRef

Schema creates a SchemaRef for type T The schema is inferred from the type structure at compile time

func (SchemaRef) BindAndValidate

func (s SchemaRef) BindAndValidate(data []byte) (any, error)

BindAndValidate binds request data to the schema type and validates it Returns the bound value or an error

func (SchemaRef) IsZero

func (s SchemaRef) IsZero() bool

IsZero returns true if the schema is not set

func (SchemaRef) Type

func (s SchemaRef) Type() reflect.Type

Type returns the underlying reflect.Type

func (SchemaRef) TypeName

func (s SchemaRef) TypeName() string

TypeName returns the schema's type name

func (SchemaRef) Validate

func (s SchemaRef) Validate(value any) error

Validate validates a value against the schema Returns nil if valid, ValidationError otherwise

type ShutdownHook

type ShutdownHook func(context.Context) error

ShutdownHook is a function called during application shutdown

type Span

type Span interface {
	// SetAttr sets an attribute on the span
	SetAttr(key string, value any)

	// End completes the span
	End()

	// Context returns a context.Context with this span
	Context() context.Context
}

Span represents a single operation within a trace

type Tracer

type Tracer interface {
	// Start begins a new span with the given name
	Start(ctx context.Context, name string) Span

	// StartWithAttributes begins a new span with initial attributes
	StartWithAttributes(ctx context.Context, name string, attrs map[string]any) Span
}

Tracer creates and manages spans

type TracingOption

type TracingOption func(*tracingConfig)

Option types for functional configuration

func OTELExporter

func OTELExporter(endpoint string) TracingOption

OTELExporter configures the OpenTelemetry exporter endpoint

func TracingSampler

func TracingSampler(rate float64) TracingOption

TracingSampler sets the sampling rate (0.0 to 1.0)

type Translations

type Translations map[string]string

Translations is a map of language code → translated message. Language codes are normalized lowercase tags like "fr", "es", "de".

Directories

Path Synopsis
examples
auth command
basic command
cache command
channel command
compress command
cors command
gx-basic command
http3 command
http3-pure command
observability command
openapi command
quickstart command
ratelimit command
router command
sse command
tls command
Package gxtest provides utilities for testing GX handlers, routers, and apps without starting a real HTTP server.
Package gxtest provides utilities for testing GX handlers, routers, and apps without starting a real HTTP server.
plugins

Jump to

Keyboard shortcuts

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