Help us shape the future of Go! Take the 2026 Go Developer Survey

gpp

package module
v1.11.8 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 39 Imported by: 0

README

goplusplus (gpp)

Go Reference Go Version Version

goplusplus (gpp) is a security-conscious Go framework for REST APIs, modular monoliths, and services. It aims to keep infrastructure code small while retaining explicit production boundaries. Capability maturity is documented in docs/readiness.md.


🎯 Developer Philosophy: Small Infrastructure Surface

goplusplus provides composable routing, binding, validation, security, observability, protocol, database, and resilience components. Applications still own their domain logic, deployment configuration, threat model, and operational validation:

Category Application integration Framework capability
Routing app.GET("/users/:id", handler) Radix tree matching, path parameters (c.Param), wildcards, and context recycling (sync.Pool).
Data Binding c.BindAndValidate(&struct) Decodes JSON body, applies built-in validation tags, and returns RFC 7807 problem details automatically on error.
Security app.Use(middleware.Security()) OWASP Security Headers (HSTS, CSP, XSS), CORS preflight, Token Bucket Rate Limiting, Panic Recovery, and Request Execution Timeouts.
Protocol Docs app.AutoSwaggerUI() Dynamic OpenAPI 3.0 spec generation, Swagger UI dashboard (/swagger), GraphQL Playground (/graphql), and gRPC HTTP/2 multiplexing.
Database db.Query(ctx, ...) PgBouncer transaction mode, primary/replica routing (RW/RO), Read-Your-Own-Writes consistency, and Slow Query Advisor (SQL fingerprinting & suggestions).
Observability middleware.Observability() Prometheus /metrics counters, OpenTelemetry X-Trace-ID distributed tracing, and slog structured logs.
Resilience cb.Execute(...) Circuit breakers, adaptive concurrency limiting, and process-local saga compensation.
Frontend SPA app.StaticEmbed("/", webFS) Serves embedded static assets with an SPA index.html fallback.

📦 Installation

go get github.com/saifsilver/goplusplus@v1.11.5

🚀 Quick Start (15 Lines of Code)

package main

import (
	"fmt"
	"net/http"

	gpp "github.com/saifsilver/goplusplus"
	"github.com/saifsilver/goplusplus/middleware"
)

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

	// Global Security & Observability Middleware
	app.Use(middleware.Logger(), middleware.Recovery(), middleware.Security())

	// API Handler
	app.GET("/api/v1/hello", func(c *gpp.Context) error {
		return c.JSON(http.StatusOK, gpp.H{
			"message": "Welcome to goplusplus!",
			"status":  "active",
		})
	})

	fmt.Println("🚀 Server running on http://localhost:8080")
	if err := app.Listen(":8080"); err != nil {
		panic(err)
	}
}

🏛️ Master Feature Catalog

1. ⚡ Radix Router & Context Pooling

High-performance HTTP routing supporting static paths, named parameters (:id), and wildcards (*path):

v1 := app.Group("/api/v1")
v1.GET("/users/:id", func(c *gpp.Context) error {
    id := c.Param("id")
    page := c.QueryDefault("page", "1")
    return c.JSON(200, gpp.H{"id": id, "page": page})
})

2. ✅ Ergonomic Struct Binding & Tag Validation

Decode JSON request payloads and validate struct constraints in 1 atomic step. The validator is implemented inside goplusplus using only the Go standard library—there is no external validation dependency. It supports type-aware bounds, comparisons, formats, cross-field and conditional rules, nested structs, and collection/map traversal:

type CreateUserRequest struct {
    Name     string   `json:"name" validate:"required,min=2,max=100"`
    Email    string   `json:"email" validate:"required,email"`
    Age      int      `json:"age" validate:"gte=18,lte=120"`
    Role     string   `json:"role" validate:"oneof=admin editor viewer"`
    Tags     []string `json:"tags" validate:"max=10,dive,required"`
    Website  string   `json:"website" validate:"omitempty,url"`
}

app.POST("/users", func(c *gpp.Context) error {
    var req CreateUserRequest
    if err := c.BindAndValidate(&req); err != nil {
        return err // Automatically returns RFC 7807 Problem Details JSON on error!
    }
    return c.JSON(201, gpp.H{"status": "created", "user": req})
})

Invalid input returns stable, machine-readable RFC 7807 JSON using the request's JSON field names:

{
  "type": "https://goplusplus.dev/errors/validation",
  "title": "Request validation failed",
  "status": 400,
  "detail": "One or more fields are invalid",
  "instance": "/users",
  "errors": [
    {"field": "name", "rule": "min", "message": "must contain at least 2 characters"}
  ]
}

Strings count Unicode code points. Slices, arrays, and maps use collection length; numeric fields use numeric value. required rejects zero values and empty collections. omitempty skips only the rules that follow it when the field is empty. Validation metadata is cached per struct type, traversal is bounded, and cycles are detected.

JSON binding requires application/json, limits bodies to 1 MiB, rejects unknown fields and multiple documents, and never exposes decoder internals. Compatibility can be enabled explicitly:

app.JSONBinding.AllowUnknownFields = true
app.JSONBinding.AllowNonJSONContentType = true
app.JSONBinding.MaxBodyBytes = 2 << 20

Built-in validation rules:

  • Presence: required, omitempty, omitnil, required_if, required_unless, required_with, required_with_all, required_without, required_without_all, plus the matching excluded_* rules.
  • Bounds and comparisons: min, max, len, eq, ne, gt, gte, lt, lte, and their *field variants.
  • Collections and choices: oneof, not_oneof, unique, dive, and keys/endkeys for maps.
  • Text: alpha, alphanum, numeric, number, lowercase, uppercase, ascii, printascii, boolean, contains*, excludes*, startswith, and endswith.
  • Formats: email, url, http_url, ip, ipv4, ipv6, cidr, cidrv4, cidrv6, hostname, hostname_port, uuid, uuid3, uuid4, uuid5, json, base64, base64url, hexadecimal, hexcolor, and datetime.

Unknown rules and malformed parameters fail closed as internal configuration errors; they are never silently skipped.


3. 🚀 Parallel Concurrency & DB Query Execution

Execute multiple asynchronous tasks or database queries concurrently in parallel goroutines with context cancellation and panic safety:

// Parallel Async Task Execution
err := c.Parallel(
    func(c *gpp.Context) error { return fetchUserProfile(c) },
    func(c *gpp.Context) error { return fetchUserOrders(c) },
    func(c *gpp.Context) error { return fetchUserMetrics(c) },
)

// Concurrent Parallel Database Queries across Replicas
err = db.ParallelQuery(ctx,
    dbcore.ParallelTask{QueryName: "user.fetch", SQL: "SELECT * FROM users WHERE id=$1", Args: []any{"42"}},
    dbcore.ParallelTask{QueryName: "orders.fetch", SQL: "SELECT * FROM orders WHERE user_id=$1", Args: []any{"42"}},
)

4. 🔐 Type-Safe Context Storage & Retrieval

Store request-scoped variables and safely retrieve them with automatic type coercion or generic inference:

app.Use(func(c *gpp.Context) error {
    c.Set("user_id", int64(1001))
    c.Set("role", "admin")
    return c.Next()
})

app.GET("/profile", func(c *gpp.Context) error {
    // 1. Direct Typed Getters (Safe conversion across int/int64/float64/string)
    userID := c.GetInt64("user_id") // 1001
    role   := c.GetString("role")   // "admin"

    // 2. Single-Value any Getter (Prevents Go syntax multi-value assertion errors)
    val := c.GetAny("user_id").(int64)

    // 3. Generic Getter Functions (Go 1.18+)
    userID, ok := gpp.GetAs[int64](c, "user_id")
    tenantID   := gpp.GetOrDefault[string](c, "tenant_id", "default_tenant")

    return c.JSON(200, gpp.H{"user_id": userID, "role": role})
})

5. ⚛️ Embedded React / Vite / Next.js SPA Serving

Serve embedded React/Vite/Next.js frontend assets directly out of a single Go binary with Automatic Client-Side SPA Fallback Routing:

// Embed built static assets directly into the binary
//go:embed dist/*
var distFS embed.FS

app.StaticFS("/", distFS) // Serves assets and falls back to index.html for SPA routes!

6. 🌐 Triple-Auto Generators (Swagger, GraphQL, gRPC)

Auto-generate interactive Swagger OpenAPI documentation, GraphQL Playgrounds, and gRPC Web endpoints with zero manual schema setup:

app.GET("/swagger", app.AutoSwaggerUI())
app.GET("/graphql", app.AutoGraphQLPlayground("/graphql"))
app.POST("/graphql", app.AutoGraphQLHandler())
app.POST("/grpc/*", app.AutoGRPCHandler())

7. 🏛️ Modular Monolith & Microservices Architecture

Organize domain features into clean gpp.Module implementations:

type UserModule struct{}

func (m *UserModule) Name() string { return "UserModule" }
func (m *UserModule) Register(group *gpp.RouterGroup) {
    group.GET("/profile/:id", m.getProfile)
}

func (m *UserModule) getProfile(c *gpp.Context) error {
    return c.JSON(200, gpp.H{"id": c.Param("id")})
}

// In main.go (Monolith Mode):
app.RegisterModule("/api/v1/users", &UserModule{})

7. 🗄️ dbcore Production Database Access & Slow Query Advisor

Handles PgBouncer transaction mode, primary (RW) / replica (RO) routing, Read-Your-Own-Writes consistency, and automated Slow Query Advisor:

import "github.com/saifsilver/goplusplus/dbcore"

db, _ := dbcore.NewClient(ctx, dbcore.Config{
    RWDSN: "postgres://app_rw:...@pgbouncer:6432/app_rw",
    RODSN: "postgres://app_ro:...@pgbouncer:6432/app_ro",
    SlowQuery: dbcore.SlowQueryConfig{Threshold: 250 * time.Millisecond},
})

// Attach query name for dashboards
reqCtx := dbcore.WithQueryName(c.Request.Context(), "user.search")

// Read Query (Auto-routes to Replica RO)
err := db.Query(reqCtx, "SELECT id, name FROM users WHERE id=$1", fn, "42")

// Transaction Write (Auto-routes to Primary RW)
err = db.InTx(reqCtx, func(tx *sql.Tx) error {
    return nil
})

8. 🛡️ Resilience Suite (Circuit Breaker & Adaptive Limiter)

Protect downstream services from cascading failures and traffic spikes when the application supplies appropriate limits and failure policies:

// 1. Circuit Breaker
cb := resilience.NewCircuitBreaker(resilience.CircuitBreakerConfig{
    FailureThreshold: 5,
    ResetTimeout:     10 * time.Second,
})

err := cb.Execute(func() error {
    return callExternalPaymentAPI()
})

// 2. Adaptive Concurrency Limiter (Little's Law)
app.Use(resilience.NewAdaptiveLimiter(1000).Middleware())

9. 🔄 Process-Local Saga Coordination (saga)

Coordinate in-process steps with reverse compensation on failure. This helper is not durable and does not replace a workflow engine for distributed production work:

sagaCoord := saga.NewCoordinator()

sagaCoord.AddStep("reserve_stock",
    func(ctx context.Context) error { return reserveStock() },
    func(ctx context.Context) error { return releaseStock() }, // Auto-compensation on error!
)

sagaCoord.AddStep("charge_payment",
    func(ctx context.Context) error { return chargePayment() },
    func(ctx context.Context) error { return refundPayment() },
)

err := sagaCoord.Execute(ctx)

⚡ Process-Local Background Task Tracker (queue)

Dispatch best-effort background tasks with automatic retries and process-local status visibility. Use Kafka, RabbitMQ, or another durable queue when work must survive restarts:

// 1. Dispatch tracked background task (returns task ID)
app.POST("/api/v1/tasks/send-email", func(c *gpp.Context) error {
    taskID := c.AsyncTask("send_welcome_email", func(c *gpp.Context) error {
        return sendEmailSMTP() // Automatically retries up to 3 times on failure!
    })
    return c.JSON(http.StatusAccepted, gpp.H{"task_id": taskID})
})

// 2. Query task status anytime by ID
app.GET("/api/v1/tasks/:id", func(c *gpp.Context) error {
    taskInfo, _ := c.GetTaskStatus(c.Param("id"))
    // Returns: task.Status ("PENDING"|"RUNNING"|"COMPLETED"|"FAILED"|"RETRYING"), Retries, LastError
    return c.JSON(http.StatusOK, gpp.H{"task": taskInfo})
})

📡 Real-Time WebSockets & Server-Sent Events (SSE) Suite (realtime)

goplusplus includes zero-dependency support for real-time WebSocket messaging and Server-Sent Events (SSE):

// 1. Server-Sent Events (SSE) Live Stream
app.GET("/api/v1/sse", func(c *gpp.Context) error {
    eventChan := make(chan any)
    go func() {
        eventChan <- realtime.SSEEvent{Event: "notice", Data: "Live Update!"}
    }()
    return realtime.StreamSSE(c, eventChan)
})

// 2. WebSocket Real-Time Upgrade
app.GET("/api/v1/ws", func(c *gpp.Context) error {
    conn, err := realtime.Upgrade(c)
    if err != nil { return err }
    defer conn.Close()

    msg, _ := conn.ReadMessage()
    return conn.WriteMessage("Echo: " + msg)
})

🔮 Probabilistic Data Structures & Cache Defense (bloom)

High-performance Bloom Filters, HyperLogLog DAU counters, and Count-Min Sketch frequency estimators:

// 1. Bloom Filter (Zero-False Negative Cache Penetration Defense)
bloomFilter := bloom.NewFilter(10000, 0.01)
bloomFilter.Add("usr_101")

if !bloomFilter.MayContain(id) {
    return gpp.ErrNotFound("User 100% does not exist in DB") // Blocks malicious DB attack!
}

// 2. HyperLogLog (Constant Memory Unique Visitor Counter)
hll := bloom.NewHyperLogLog()
hll.Add("user_ip_1")
daus := hll.EstimateCardinality()

// 3. Count-Min Sketch (Top-K Trending Frequency Estimator)
cms := bloom.NewCountMinSketch()
cms.Add("trending_topic", 1)

🔒 Universal Security & Authentication Engine

goplusplus includes multi-platform security for Web and Mobile applications:

// 1. Immutable password policy (Argon2id, timing guard, migration decisions)
passwords, err := auth.NewPasswordPolicy(auth.PasswordPolicyConfig{
    Pepper: passwordPepper, Argon2id: auth.DefaultPasswordConfig(),
})
if err != nil { return err }
passwordHash, err := passwords.Hash(password)

// 2. JWT policy with explicit issuer, audience, key ID, rotation set, and TTL
tokens, err := auth.NewTokenManager(auth.TokenConfig{
    Issuer: "https://api.example.com",
    Audience: "example-api",
    ActiveKeyID: "2026-08",
    Keys: map[string][]byte{"2026-08": signingKey}, // at least 32 random bytes
    MaxTTL: 24 * time.Hour,
    ClockSkew: time.Minute,
})
if err != nil { return err }
jwtToken, err := tokens.IssueUser(userClaims, 15*time.Minute)

// 3. Server-side HTTP-only SameSite cookie sessions
sessionMgr, err := auth.NewSessionManager(auth.SessionConfig{
    TTL: 8 * time.Hour, SameSite: http.SameSiteLaxMode,
})
if sessionMgr.CreateSession(c, userClaims) == "" { return errors.New("session creation failed") }

// 4. Accept a verified cookie session or signed JWT
app.Use(auth.UniversalAuthWithManager(tokens, sessionMgr))

Bearer and session middleware now install one verified identity for auth.GetUser, roles, policies, RequireUserSubject (UUID/string IDs), and RequireUserID (positive numeric IDs). Bearer syntax is exactly one case-sensitive Authorization: Bearer <token> header.

Use explicit deadlines for every legacy adapter. The signed pre-v1.11 two-part token and HMAC password hash are the only built-in historical formats. Unsigned placeholder JWT/PASETO strings remain rejected. See the production authentication guide, v1.11.1 authentication migration, and SQL-backed application example.


⚙️ Configuration & Secret Vault Suite (config)

Zero-dependency .env file loader, type-safe getters, secret masker, and struct tag unmarshaler:

// 1. Load .env file automatically
_ = config.Load(".env")

// 2. Unmarshal into struct via `env:"KEY"` tags
type AppConfig struct {
    Port   string `env:"PORT" default:":8080"`
    DBURL  string `env:"DATABASE_URL"`
    Secret string `env:"JWT_SECRET"`
}

var cfg AppConfig
_ = config.Unmarshal(&cfg)

// 3. Type-Safe Getters & Secret Masker
port   := config.GetString("PORT", ":8080")
conns  := config.GetInt("MAX_CONNS", 100)
secret := config.MaskSecret(cfg.Secret) // Redacts secret: "sup...91823"

☁️ Cloud Infrastructure Suite (SQLite, S3, CloudFront, Elasticsearch, Kafka, RabbitMQ)

goplusplus includes built-in driver adapters for enterprise cloud services:

// 1. AWS S3 & CloudFront CDN
s3Client := storage.NewS3Client(storage.S3Config{Bucket: "app-assets", Region: "us-east-1"})
s3URL, _ := s3Client.Upload(ctx, "logo.png", data, "image/png")
cdnURL  := storage.GenerateCloudFrontURL("cdn.myapp.com", "logo.png")

// 2. Zero-Config Embedded SQLite Database
sqliteDB, _ := dbcore.NewSQLiteClient("app.db")

// 3. Distributed Redis & L1 Memory Cache (Single-Flight Stampede Protection)
redisCache := cache.NewRedisClient("redis://localhost:6379/0")
val, _     := redisCache.GetOrSet(ctx, "user:101", 10*time.Minute, func() (any, error) {
    return fetchUserFromDB(101)
})

// 4. Elasticsearch & OpenSearch
esClient := search.NewElasticsearchClient(search.ESConfig{})
_ = esClient.IndexDocument(ctx, "products", "prod_1", payload)

// 5. Kafka & RabbitMQ Messaging
kafkaWorker := queue.NewKafkaWorker([]string{"localhost:9092"}, "events")
rabbitBus   := pubsub.NewRabbitMQBus("amqp://localhost:5672")

Search resources declare every queryable dynamic attribute once. The same typed request contract powers Go, REST, and GraphQL, so clients cannot inject database columns, SQL fragments, or backend-specific query DSL.

schema, err := search.NewSchema(
	search.AttributeDefinition{
		Key: "title", Type: search.AttributeString, Searchable: true,
	},
	search.AttributeDefinition{
		Key: "brand", Type: search.AttributeEnum,
		Filterable: true, Facetable: true,
		EnumValues: []string{"Nike", "Adidas"},
	},
	search.AttributeDefinition{
		Key: "price", Type: search.AttributeDecimal,
		Filterable: true, Sortable: true,
	},
	search.AttributeDefinition{
		Key: "tenant_id", Type: search.AttributeString, Filterable: true,
	},
)
if err != nil {
	return err
}

backend, err := search.NewDatabaseBackend(db, search.DatabaseConfig{})
if err != nil {
	return err
}
if err := backend.Setup(ctx); err != nil {
	return err
}

products, err := search.NewResource("products", schema, backend)
if err != nil {
	return err
}

For tenant- or authorization-scoped resources, add mandatory filters with search.WithScope. Scope filters always constrain hits and facet counts, including disjunctive facets:

products, err := search.NewResource("products", schema, backend,
	search.WithScope(func(ctx context.Context) ([]search.Filter, error) {
		return []search.Filter{
			{Field: "tenant_id", Operator: search.OperatorEqual, Value: tenantIDFrom(ctx)},
		}, nil
	}),
)

Index and search dynamic documents:

_ = products.Index(ctx, search.Document{
	ID: "prod_1",
	Attributes: map[string]any{
		"title": "Road running shoe",
		"brand": "Nike",
		"price": 120.00,
	},
})

result, err := products.Search(ctx, search.SearchRequest{
	Query: "running",
	Filters: []search.Filter{
		{Field: "price", Operator: search.OperatorBetween, Value: []float64{50, 150}},
	},
	Facets: []search.FacetRequest{
		{Field: "brand", Mode: search.FacetDisjunctive},
	},
})

Bind a REST endpoint and the schema-validated GraphQL field:

registry, _ := search.NewRegistry(products)

gpp.BindSearchResource(v1, "/products/search", products)
_ = gpp.BindSearchGraphQL(app, "productSearch", registry)

app.POST("/graphql", app.AutoGraphQLHandler())
query ProductSearch($request: SearchRequestInput!) {
  productSearch(resource: "products", request: $request) {
    total
    nextCursor
    items { id score attributes }
    facets { field buckets { value count } }
  }
}

Choose the backend explicitly per resource:

  • Database (default): use for exact transactional results, moderate query volume, simple full-text search, and minimal operational overhead. The built-in backend targets PostgreSQL JSONB with GIN indexes.
  • Elasticsearch/OpenSearch: use when relevance ranking, typo tolerance, stemming, synonyms, autocomplete, high-volume aggregations, or many multi-value facets justify a separate eventually-consistent index.
  • Hybrid: use Elasticsearch for ranking/facets and hydrate authorized records from the database. Tenant and authorization filters must be applied before both hits and facet counts are calculated.

Facets are disjunctive by default: a filter on brand is excluded while computing the brand buckets, preserving alternative brand counts. Set Mode: search.FacetConjunctive when selected filters should narrow their own facet.


✅ Pre-Push Quality Gate

Install the repository-managed hook once per clone:

make install-hooks

Every git push then runs the same gate as CI:

make verify

The gate checks:

  • gofmt formatting without modifying files
  • go vet ./...
  • go test ./... with atomic coverage collection
  • a repository-wide coverage floor (initially 55%; override with COVERAGE_MIN=60 make coverage)
  • go mod verify
  • the pinned official Go govulncheck vulnerability scanner

The tracked hook is a developer feedback mechanism; GitHub Actions remains authoritative because local hooks can be bypassed with --no-verify.

Release tagging

Create the next patch release from a clean worktree. The command updates gpp.Version, creates a release commit, and adds an annotated Git tag:

make tag

Choose a specific semantic version when publishing a minor or major release:

make tag VERSION=v1.12.0

The tag remains local until explicitly published with git push origin <tag>.


🧪 Ergonomic E2E Integration Testing Suite (gpptest)

Write 3-line E2E API integration tests without starting real network sockets:

func TestCreateUser(t *testing.T) {
    tester := gpptest.New(t, app)
    res := tester.POST("/api/v1/users", gpp.H{"name": "Alice", "email": "alice@dev.com"})
    res.AssertStatus(201)
    res.AssertJSON("status", "created")
}

⚡ cmd/gpp CLI Code Generator

Install the CLI tool to scaffold a compile-tested modular monolith with explicit domain and infrastructure boundaries:

# Install CLI
go install github.com/saifsilver/goplusplus/cmd/gpp@latest

# Launch Vite-style Interactive Wizard (when run without arguments in a TTY terminal)
gpp

# Or force interactive mode in any shell
gpp -i

# Direct CLI command mode:
# Scaffold a new app (the module flag is recommended for published projects)
gpp new myapp --module github.com/acme/myapp

# Generate domain module
gpp gen module order

# Extract a portable module into a standalone HTTP service
gpp extract service order --module github.com/acme/order-service

# Generate deployment targets from the application root
gpp gen terraform aws
gpp gen hosting standard

The generated application uses this structure:

myapp/
├── cmd/api/                         # process entrypoint
├── internal/application/            # composition root
├── internal/config/                 # validated environment config
├── internal/modules/
│   ├── system/                     # liveness/readiness
│   └── users/                      # domain, service, repository, HTTP, migrations
└── services/                         # optional extracted service modules

Business modules own their contracts and persistence adapters and are wired only in internal/application. This keeps in-process monolith calls cheap while preserving a clear extraction boundary for future microservices. Scaffold creation is atomic, refuses to overwrite existing directories, validates the Go module path, includes secure production configuration checks, and generates integration tests that run without network sockets.

Portable modules expose Build(*dbcore.Client) and Migrations(). The extraction command audits internal imports, refuses hidden cross-module dependencies, copies and rewrites the module into an independently buildable service, and leaves the monolith untouched for a controlled data and traffic cutover. HTTP is the default and only extraction transport currently exposed.

The AWS target generates private ECS Fargate services behind an HTTPS load balancer, encrypted RDS credentials managed by Secrets Manager, immutable ECR images, multi-AZ networking, deployment rollback, CloudWatch logs, and autoscaling. The standard target generates a portable Docker Compose deployment with Caddy automatic HTTPS, PostgreSQL health ordering, mounted secrets, persistent volumes, and backups for a conventional VPS.


🧱 Dependency Injection & Lifecycle Hooks (di) — Uber FX-Style

Constructor dependency injection container with startup and shutdown hooks:

container := di.New()

container.OnStart(func() error {
    log.Println("Database connection pool initialized")
    return nil
})

_ = container.Start()
defer func() { _ = container.Stop() }()

11. 📌 RFC 8594 API Versioning Engine

Multi-strategy API version negotiation (Header X-API-Version, Query ?v=1, Accept header) with RFC 8594 deprecation and sunset date HTTP headers:

vm := versioning.NewManager("v1")
vm.Deprecate("v1", "2027-01-01") // Warns v1 clients with Sunset HTTP headers!

app.Use(vm.Middleware())

12. 🩺 Kubernetes Health Probes & Structured Audit Events

Kubernetes /healthz/liveness and /healthz/readiness probes plus structured audit events. Tamper evidence, durable retention, and compliance controls must be provided by the configured audit pipeline:

healthChecker := health.NewChecker()
healthChecker.AddReadinessCheck("database", func(ctx context.Context) error { return db.Ping() })

app.GET("/healthz/liveness", healthChecker.Liveness())
app.GET("/healthz/readiness", healthChecker.Readiness())

// Security Audit Event
audit.Log(ctx, "user_admin", "UPDATE_ROLE", "user_42", map[string]any{"new_role": "admin"})

13. 🌐 Enterprise Platform Suite (i18n, tenant, auth, notify)
  • Internationalization (i18n): BCP 47/Accept-Language negotiation, runtime catalogs, CLDR plural rules, interpolation, locale-aware numbers and percentages, exact ISO 4217 money, IANA time zones, localized date/time styles, and RTL/LTR metadata.
  • Multi-Tenancy (tenant): Tenant extraction from headers/subdomains.
  • Security (auth): JWT authentication, RBAC, ABAC, and TOTP 2FA MFA.
  • Notifications (notify): Email SMTP & SMS dispatch.
bundle := i18n.NewBundle("en")
_ = bundle.AddMessages("de", map[string]string{
    "welcome %s": "Willkommen, %s",
})
_ = bundle.AddPlural("de", "results", i18n.PluralForms{
    One:   "ein Ergebnis",
    Other: "%d Ergebnisse",
})
app.Use(bundle.Middleware()) // ?lang=de or weighted Accept-Language

// Store money as minor units, never float64: USD 1,234.56 = 123456 cents.
price, err := i18n.FormatMoney(i18n.Money{
    MinorUnits: 123456,
    Currency:   "USD",
}, "fr-FR")

createdAt, err := bundle.FormatDateTime(
    time.Now(),
    "en-GB",
    "Europe/London",
    i18n.DateTimeOptions{DateStyle: i18n.Long, TimeStyle: i18n.Short},
)

The middleware stores the canonical language under i18n.ContextLanguageKey, the full i18n.Locale under i18n.ContextLocaleKey, and emits Content-Language plus Vary: Accept-Language. English, Spanish, and French starter catalogs/date profiles are included; applications register their own messages and may add regional date-time profiles with RegisterDateTimeProfile.


14. 🛠️ Production Suite: Migrations, Seeder/Faker, Idempotency, Singleflight & Pagination
  • SQL Migrations (dbcore.AutoMigrate, dbcore.MigrateEmbed): Auto-executes transactional migrations tracked in gpp_migrations.
  • DB Seeder & Faker (seed.Run, seed.Faker): Seed fake data (f.Name(), f.Email(), f.UUID(), f.Phone()) in 1 batch operation.
  • Idempotency Key (middleware.Idempotency()): Caches write responses for Idempotency-Key headers to prevent duplicate side-effects.
  • Singleflight Deduplication (middleware.Singleflight()): Deduplicates concurrent identical GET requests to prevent thundering herd.
  • High-Performance Pagination (c.Paginate, c.PaginateCursor): Standardized page-based and $O(1)$ cursor-based pagination.
// 1. Auto-Run SQL Migrations from embed.FS
//go:embed migrations/*.sql
var migrationFiles embed.FS
_ = dbcore.MigrateEmbed(ctx, db, migrationFiles, "migrations")

// 2. Batch Seed Fake Users
_ = seed.Run(ctx, db, seed.Plan{
    Table: "users",
    Count: 50,
    Factory: func(f *seed.Faker) map[string]any {
        return map[string]any{"name": f.Name(), "email": f.Email(), "role": f.Select("admin", "user")}
    },
})

// 3. High-Performance Cursor Pagination Handler
app.GET("/api/v1/feed", func(c *gpp.Context) error {
    cursor, limit := c.GetCursorAndLimit(20)
    result, err := userRepo.PaginateCursor(c.Request.Context(), "id", cursor, limit)
    if err != nil {
        return err
    }
    return c.PaginateCursor(200, result.Items, result.NextCursor, result.HasMore, result.Limit)
})

Unreleased database and request infrastructure

SQLite and PostgreSQL now use real database/sql connections. Open SQLite with dbcore.OpenSQLite(ctx, dbcore.SQLiteConfig{...}); open PostgreSQL primary and optional replica pools with dbcore.NewPostgresClient(ctx, dbcore.Config{...}). Neither adapter silently falls back to an in-memory database. Migration history is transactional and checksum-verified, and common SQLite/PostgreSQL constraint failures have stable dbcore.ErrorKind classifications.

The unreleased development branch also adds causal gpp.NewInternalError, the explicit BindNormalizeAndValidate request pipeline, strict typed parameters, PaginationPolicy, isolated config.Loader, redacted bounded readiness checks, typed gpptest response helpers, and an application-credential-neutral TypeScript HTTP transport. See MIGRATION_v1.12.md for adoption examples and compatibility details.


🤖 AI Agent Integration Guide (AGENTS.md)

goplusplus includes an AGENTS.md guide for coding assistants. Generated changes remain subject to the same review, testing, security, and readiness requirements as human-authored changes.


📁 Ready-to-Run Example Applications

Explore complete, runnable production examples in the examples/ directory:


📄 License

Distributed under the MIT License. See LICENSE for more information.

Documentation

Overview

Package gpp provides an HTTP application framework with routing, request contexts, strict binding and validation, RFC 7807 errors, generated protocol helpers, and server lifecycle management.

Applications own domain rules, authorization policy, persistence schemas, dependency construction, and deployment. Optional packages provide adapters whose production readiness is documented in docs/readiness.md.

Index

Constants

View Source
const (
	// DefaultMaxJSONBodyBytes is the default accepted JSON request size.
	DefaultMaxJSONBodyBytes int64 = 1 << 20
	// MaximumJSONBodyBytes is the hard upper bound for configured JSON request sizes.
	MaximumJSONBodyBytes int64 = 64 << 20
)
View Source
const Version = "v1.11.8"

Version is the current release version of the goplusplus framework.

Variables

This section is empty.

Functions

func BindResource

func BindResource[T any](group *RouterGroup, relativePath string, repo *dbcore.Repository[T])

BindResource automatically mounts a complete set of RESTful CRUD routes (GET /, GET /:id, POST /, PUT /:id, DELETE /:id) for entity T using dbcore.Repository[T].

func BindSearchGraphQL

func BindSearchGraphQL(engine *Engine, fieldName string, registry *search.Registry) error

BindSearchGraphQL registers a typed search query field backed by registry.

func BindSearchResource

func BindSearchResource(group *RouterGroup, relativePath string, resource *search.Resource)

BindSearchResource registers a JSON search endpoint on group.

func GetAs

func GetAs[T any](c *Context, key string) (T, bool)

GetAs retrieves a context value typed as T if present and matching type T.

func GetOrDefault

func GetOrDefault[T any](c *Context, key string, defaultValue T) T

GetOrDefault retrieves a context value typed as T, or returns defaultValue if not set or wrong type.

func IsInternalFailure

func IsInternalFailure(err error) bool

IsInternalFailure reports whether err represents a server-side failure.

func MustGetAs

func MustGetAs[T any](c *Context, key string) T

MustGetAs retrieves a context value typed as T or panics if not set or wrong type.

func TotalPages

func TotalPages(total, limit int) (int, error)

TotalPages calculates the page count for a non-negative total and positive limit.

Types

type CLIOptions

type CLIOptions struct {
	Client     *dbcore.Client
	Migrations []dbcore.Migration
	SeedPlans  []seed.Plan
	Args       []string // Optional override args for testing (defaults to os.Args if empty)
}

CLIOptions defines configuration for application binary CLI flags.

type Context

type Context struct {
	Writer  http.ResponseWriter
	Request *http.Request
	Params  Params
	// contains filtered or unexported fields
}

Context represents the request-scoped context containing Request, ResponseWriter, and parameter metadata.

func (*Context) Abort

func (c *Context) Abort()

Abort stops the execution of remaining handlers in the current request chain.

func (*Context) AbortWithStatusJSON

func (c *Context) AbortWithStatusJSON(statusCode int, payload any) error

AbortWithStatusJSON aborts execution and writes a JSON error payload immediately.

func (*Context) Accepted

func (c *Context) Accepted(data any) error

Accepted writes an HTTP 202 Accepted JSON response for asynchronous operations.

func (*Context) Async

func (c *Context) Async(fn func(c *Context) error)

Async dispatches a non-blocking background task in a detached goroutine with panic safety.

func (*Context) AsyncTask

func (c *Context) AsyncTask(name string, fn func(c *Context) error) string

AsyncTask dispatches a background task with automatic retries on failure and persistent status tracking, returning a task ID.

func (*Context) BadRequest

func (c *Context) BadRequest(message string) error

BadRequest writes an HTTP 400 Bad Request error response.

func (*Context) BindAndValidate

func (c *Context) BindAndValidate(v any) error

BindAndValidate decodes the JSON request body and validates struct fields in a single atomic step.

func (*Context) BindJSON

func (c *Context) BindJSON(v any) error

BindJSON securely parses one JSON document into a non-nil pointer.

func (*Context) BindNormalizeAndValidate

func (c *Context) BindNormalizeAndValidate(v any, normalize NormalizeFunc) error

BindNormalizeAndValidate executes the explicit request processing pipeline.

func (*Context) Body

func (c *Context) Body() ([]byte, error)

Body reads the raw bytes from the request body.

func (*Context) Conflict

func (c *Context) Conflict(message string) error

Conflict writes an HTTP 409 Conflict error response.

func (*Context) Created

func (c *Context) Created(data any) error

Created writes an HTTP 201 Created JSON response.

func (*Context) Data

func (c *Context) Data(statusCode int, contentType string, data []byte) error

Data writes raw binary data with a specified content type.

func (*Context) Delete

func (c *Context) Delete(key string)

Delete removes a key from request context storage.

func (*Context) File

func (c *Context) File(filepath string) error

File serves a static file from disk.

func (*Context) Forbidden

func (c *Context) Forbidden(message string) error

Forbidden writes an HTTP 403 Forbidden error response.

func (*Context) Get

func (c *Context) Get(key string) (any, bool)

Get retrieves a stored value by key from the request context storage.

func (*Context) GetAny

func (c *Context) GetAny(key string) any

GetAny retrieves a stored value by key as a single return value (nil if not found).

func (*Context) GetBool

func (c *Context) GetBool(key string) bool

GetBool retrieves a stored value converted to bool. Returns false if not found or unconvertible.

func (*Context) GetCursorAndLimit

func (c *Context) GetCursorAndLimit(defaultLimit ...int) (string, int)

GetCursorAndLimit parses query parameters 'cursor' and 'limit' with safe fallback defaults.

func (*Context) GetFloat64

func (c *Context) GetFloat64(key string) float64

GetFloat64 retrieves a stored value converted to float64. Returns 0.0 if not found or unconvertible.

func (*Context) GetHeader

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

GetHeader gets an HTTP request header.

func (*Context) GetInt

func (c *Context) GetInt(key string) int

GetInt retrieves a stored value converted to int. Returns 0 if not found or unconvertible.

func (*Context) GetInt64

func (c *Context) GetInt64(key string) int64

GetInt64 retrieves a stored value converted to int64. Returns 0 if not found or unconvertible.

func (*Context) GetPageAndLimit

func (c *Context) GetPageAndLimit(defaultLimit ...int) (int, int)

GetPageAndLimit parses query parameters 'page' and 'limit' with safe fallback defaults.

func (*Context) GetString

func (c *Context) GetString(key string) string

GetString retrieves a stored string value from context storage, converting numeric/boolean values if necessary.

func (*Context) GetTaskStatus

func (c *Context) GetTaskStatus(taskID string) (*queue.TaskInfo, bool)

GetTaskStatus retrieves the status and retry details of a background task by ID.

func (*Context) HTML

func (c *Context) HTML(statusCode int, html string) error

HTML renders an HTML string response with text/html content type.

func (*Context) InternalError

func (c *Context) InternalError(message string) error

InternalError writes an HTTP 500 Internal Server Error response.

func (*Context) IsAborted

func (c *Context) IsAborted() bool

IsAborted returns true if the current context request chain has been aborted.

func (*Context) IsCancelled

func (c *Context) IsCancelled() bool

IsCancelled returns true if the client closed the browser connection or cancelled the request.

func (*Context) JSON

func (c *Context) JSON(statusCode int, data any) error

JSON serializes the given data struct into JSON and writes it with the status code.

func (*Context) MustGet

func (c *Context) MustGet(key string) any

MustGet retrieves a value by key or panics if not found.

func (*Context) Next

func (c *Context) Next() error

Next executes the remaining handlers in the chain.

func (*Context) NoContent

func (c *Context) NoContent() error

NoContent writes an HTTP 204 No Content response with zero body.

func (*Context) NotFound

func (c *Context) NotFound(message string) error

NotFound writes an HTTP 404 Not Found error response.

func (*Context) OK

func (c *Context) OK(data any) error

OK writes an HTTP 200 OK JSON response.

func (*Context) Paginate

func (c *Context) Paginate(statusCode int, items any, page, limit, total int) error

Paginate writes a standardized offset-based paginated JSON response.

func (*Context) PaginateCursor

func (c *Context) PaginateCursor(statusCode int, items any, nextCursor string, hasMore bool, limit int) error

PaginateCursor writes a standardized O(1) high-performance cursor-based paginated JSON response.

func (*Context) Parallel

func (c *Context) Parallel(tasks ...func(c *Context) error) error

Parallel executes multiple task functions concurrently in parallel goroutines.

func (*Context) Param

func (c *Context) Param(key string) string

Param retrieves a path parameter by name (e.g. /users/:id -> c.Param("id")).

func (*Context) ParamInt

func (c *Context) ParamInt(key string, defaultValue ...int) int

ParamInt retrieves a path parameter converted directly to int with optional default fallback.

func (*Context) ParamInt64

func (c *Context) ParamInt64(key string, defaultValue ...int64) int64

ParamInt64 retrieves a path parameter converted directly to int64 with optional default fallback.

func (*Context) ParamInt64Strict

func (c *Context) ParamInt64Strict(key string) (int64, error)

ParamInt64Strict parses a required path parameter as an int64.

func (*Context) ParamIntStrict

func (c *Context) ParamIntStrict(key string) (int, error)

ParamIntStrict parses a required path parameter without fallback behavior.

func (*Context) ParamPositiveInt64

func (c *Context) ParamPositiveInt64(key string) (int64, error)

ParamPositiveInt64 parses a required positive int64 path parameter.

func (*Context) ParamUUIDStrict

func (c *Context) ParamUUIDStrict(key string) (string, error)

ParamUUIDStrict validates a required UUID path parameter.

func (*Context) PathValue

func (c *Context) PathValue(key string) string

PathValue is an alias for Param, providing Go 1.22+ r.PathValue() compatibility.

func (*Context) Problem

func (c *Context) Problem(problem ProblemDetails) error

Problem writes an RFC 7807/9457 Problem Details response.

func (*Context) Query

func (c *Context) Query(key string) string

Query retrieves a URL query parameter by name.

func (*Context) QueryBool

func (c *Context) QueryBool(key string, defaultValue ...bool) bool

QueryBool retrieves a query parameter converted to boolean with optional default fallback.

func (*Context) QueryDefault

func (c *Context) QueryDefault(key, defaultValue string) string

QueryDefault retrieves a URL query parameter by name, returning defaultValue if empty.

func (*Context) QueryInt

func (c *Context) QueryInt(key string, defaultValue ...int) int

QueryInt retrieves a query parameter converted to integer with optional default fallback.

func (*Context) QueryInt64Strict

func (c *Context) QueryInt64Strict(key string) (int64, error)

QueryInt64Strict parses a required query parameter as an int64.

func (*Context) QueryOptionalInt64Strict

func (c *Context) QueryOptionalInt64Strict(key string) (*int64, error)

QueryOptionalInt64Strict parses an optional int64 query parameter.

func (*Context) Redirect

func (c *Context) Redirect(code int, location string) error

Redirect sends an HTTP redirect response.

func (*Context) RequestID

func (c *Context) RequestID() string

RequestID returns the active request ID from context or HTTP header.

func (*Context) RequireUserID

func (c *Context) RequireUserID() (int64, error)

RequireUserID returns the active authenticated user ID, or returns a 401 Unauthorized error if unauthenticated.

func (*Context) RequireUserSubject

func (c *Context) RequireUserSubject() (string, error)

RequireUserSubject returns the canonical string identity or a 401 error.

func (*Context) Retry

func (c *Context) Retry(maxAttempts int, fn func(c *Context) error) error

Retry executes a function with up to maxAttempts automatic retries on error.

func (*Context) RunWithTimeout

func (c *Context) RunWithTimeout(duration time.Duration) error

RunWithTimeout executes the remaining handler chain against an isolated, buffered response. Only the request goroutine commits a response.

func (*Context) SSE

func (c *Context) SSE(eventChan <-chan any) error

SSE streams Server-Sent Events from a channel continuously.

func (*Context) Set

func (c *Context) Set(key string, value any)

Set stores a key-value pair in the request context storage.

func (*Context) SetHeader

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

SetHeader sets an HTTP response header.

func (*Context) Status

func (c *Context) Status(code int)

Status sets the HTTP response status code.

func (*Context) String

func (c *Context) String(statusCode int, format string, values ...any) error

String formats and writes a plain text string response.

func (*Context) Unauthorized

func (c *Context) Unauthorized(message string) error

Unauthorized writes an HTTP 401 Unauthorized error response.

func (*Context) UserID

func (c *Context) UserID() int64

UserID extracts the active authenticated user ID (int64) from request context storage ("user_id" or "sub").

func (*Context) UserSubject

func (c *Context) UserSubject() string

UserSubject returns the canonical authenticated string identity. Unlike UserID, it supports UUIDs and other bounded opaque identifiers.

func (*Context) Validate

func (c *Context) Validate(v any) error

Validate executes validation rules declared in validate struct tags and returns RFC 7807 problem details on failure.

func (*Context) Value

func (c *Context) Value(key string) any

Value retrieves a stored value by key as a single return value (nil if not found), compatible with context.Context interface style.

type Engine

type Engine struct {
	RouterGroup

	NotFoundHandler HandlerFunc
	ErrorHandler    func(c *Context, err error)
	Server          *http.Server
	ReadTimeout     time.Duration
	WriteTimeout    time.Duration
	IdleTimeout     time.Duration
	MaxHeaderBytes  int
	ShutdownTimeout time.Duration
	JSONBinding     JSONBindingConfig
	// contains filtered or unexported fields
}

Engine is the central core of the go++ framework, serving as router, HTTP server wrapper, and handler.

func New

func New() *Engine

New creates a fresh instance of the go++ engine with high-performance default configurations.

func (*Engine) AutoGRPCMultiplex

func (engine *Engine) AutoGRPCMultiplex(grpcHandler http.Handler) HandlerFunc

AutoGRPCMultiplex returns middleware that automatically detects gRPC requests over HTTP/2 and multiplexes them to a gRPC server.

func (*Engine) AutoGraphQLHandler

func (engine *Engine) AutoGraphQLHandler() HandlerFunc

AutoGraphQLHandler executes schema-validated GraphQL queries over registered fields.

func (*Engine) AutoGraphQLPlayground

func (engine *Engine) AutoGraphQLPlayground(graphqlEndpoint string) HandlerFunc

AutoGraphQLPlayground returns a HandlerFunc that serves the GraphQL Playground IDE automatically linked to /graphql.

func (*Engine) AutoSwaggerUI

func (engine *Engine) AutoSwaggerUI() HandlerFunc

AutoSwaggerUI returns a HandlerFunc that serves Swagger UI using the auto-generated OpenAPI spec.

func (*Engine) HandleCLI

func (engine *Engine) HandleCLI(opts CLIOptions) bool

HandleCLI inspects binary CLI flags (e.g. ./myapp migrate, ./myapp seed, ./myapp migrate:fresh). If a CLI flag is detected, it executes the target database task and returns true.

func (*Engine) Listen

func (engine *Engine) Listen(addr string) error

Listen starts an HTTP server listening on the provided address with graceful shutdown support.

func (*Engine) ListenTLS

func (engine *Engine) ListenTLS(addr, certFile, keyFile string) error

ListenTLS starts an HTTPS server listening on the provided address using TLS certificates.

func (*Engine) RegisterGraphQLQuery

func (engine *Engine) RegisterGraphQLQuery(name string, field *graphql.Field) error

RegisterGraphQLQuery adds a schema-validated field to the automatic GraphQL endpoint.

func (*Engine) RegisterModule

func (engine *Engine) RegisterModule(prefix string, module Module)

RegisterModule mounts a self-contained domain module under a specific URL path prefix.

func (*Engine) RegisterModules

func (engine *Engine) RegisterModules(modules ...Module)

RegisterModules mounts multiple domain modules onto the root engine.

func (*Engine) ServeHTTP

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements net/http.Handler using pooled request contexts.

type FieldViolation

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

FieldViolation is a machine-readable request validation failure. Values are intentionally excluded to avoid exposing passwords, tokens, or personal data.

type H

type H map[string]any

H is a convenience alias for map[string]any, enabling ultra-concise JSON responses.

type HTTPError

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

HTTPError represents a standardized structured framework error.

func NewHTTPError

func NewHTTPError(code int, message string, details ...any) *HTTPError

NewHTTPError constructs a new HTTPError with status code, message, and optional details.

func (*HTTPError) Error

func (e *HTTPError) Error() string

Error implements the standard Go error interface.

type HandlerFunc

type HandlerFunc func(c *Context) error

HandlerFunc defines the function signature for framework handlers and middleware.

type HandlersChain

type HandlersChain []HandlerFunc

HandlersChain is a slice of HandlerFunc executed in sequence.

type InternalErrorOption

type InternalErrorOption func(*InternalFailure)

InternalErrorOption configures a causal internal failure.

func WithErrorCategory

func WithErrorCategory(category string) InternalErrorOption

WithErrorCategory sets a stable internal error category.

func WithInternalStatus

func WithInternalStatus(status int) InternalErrorOption

WithInternalStatus sets a 5xx response status for the internal failure.

func WithPublicDetail

func WithPublicDetail(detail string) InternalErrorOption

WithPublicDetail opts into a caller-authored, non-sensitive 5xx detail.

func WithSafeAttributes

func WithSafeAttributes(attributes map[string]any) InternalErrorOption

WithSafeAttributes copies explicitly non-sensitive structured log attributes.

type InternalFailure

type InternalFailure struct {
	Operation    string
	Category     string
	Cause        error
	Attributes   map[string]any
	PublicDetail string
	Status       int
}

InternalFailure is a causal server-side failure. Only PublicDetail and the stable category are eligible for client rendering; Cause and Attributes are logged internally.

func NewInternalError

func NewInternalError(operation string, cause error, options ...InternalErrorOption) *InternalFailure

NewInternalError preserves cause identity while keeping the response safe.

func (*InternalFailure) Error

func (e *InternalFailure) Error() string

Error returns a sanitized internal failure summary.

func (*InternalFailure) Unwrap

func (e *InternalFailure) Unwrap() error

Unwrap returns the causal internal error.

type JSONBindingConfig

type JSONBindingConfig struct {
	MaxBodyBytes            int64
	AllowUnknownFields      bool
	AllowNonJSONContentType bool
}

JSONBindingConfig controls request JSON decoding. Zero values retain secure defaults.

type Map

type Map = map[string]any

Map is an alias for map[string]any.

type Module

type Module interface {
	Name() string
	Register(group *RouterGroup)
}

Module defines the contract for self-contained domain modules in a modular monolith.

type NormalizeFunc

type NormalizeFunc func(context.Context) error

NormalizeFunc applies application-owned normalization after binding and before validation. A nil callback is a documented no-op.

type OpenAPIGenerator

type OpenAPIGenerator struct {
	Title   string
	Version string
	// contains filtered or unexported fields
}

OpenAPIGenerator automatically inspects routes and constructs live OpenAPI 3.0 specs.

func (*OpenAPIGenerator) GenerateJSON

func (g *OpenAPIGenerator) GenerateJSON() string

GenerateJSON builds a JSON OpenAPI 3.0 specification string.

func (*OpenAPIGenerator) RegisterRoute

func (g *OpenAPIGenerator) RegisterRoute(method, pathStr string)

RegisterRoute registers route metadata into the OpenAPI specification tree.

type Pagination

type Pagination struct {
	Page   int `json:"page"`
	Limit  int `json:"limit"`
	Offset int `json:"offset"`
}

Pagination is a normalized, overflow-checked offset pagination request.

type PaginationPolicy

type PaginationPolicy struct {
	DefaultPage    int
	DefaultLimit   int
	MaximumLimit   int
	MaximumPage    int
	PageParameter  string
	LimitParameter string
	Strict         bool
}

PaginationPolicy defines names, defaults, limits, and strictness for offset pagination.

func (PaginationPolicy) Parse

func (policy PaginationPolicy) Parse(c *Context) (Pagination, error)

Parse reads and normalizes pagination parameters from c.

type Param

type Param struct {
	Key   string
	Value string
}

Param represents a single URL path parameter (e.g., key="id", value="123").

type Params

type Params []Param

Params is a slice of Param values matching the request route.

func (Params) Get

func (ps Params) Get(key string) string

Get returns the value of the first matching parameter key, or empty string if not found.

type ProblemDetails

type ProblemDetails struct {
	Type     string           `json:"type"`
	Title    string           `json:"title"`
	Status   int              `json:"status"`
	Detail   string           `json:"detail"`
	Instance string           `json:"instance,omitempty"`
	TraceID  string           `json:"trace_id,omitempty"`
	Errors   []FieldViolation `json:"errors,omitempty"`
}

ProblemDetails implements the RFC 7807 standard specification for HTTP API Problem Details.

func ErrBadRequest

func ErrBadRequest(detail string) *ProblemDetails

ErrBadRequest creates an RFC 7807 400 Bad Request problem details error.

func ErrConflict

func ErrConflict(detail string) *ProblemDetails

ErrConflict creates an RFC 7807 409 Conflict problem details error.

func ErrForbidden

func ErrForbidden(detail string) *ProblemDetails

ErrForbidden creates an RFC 7807 403 Forbidden problem details error.

func ErrInternal

func ErrInternal(detail string) *ProblemDetails

ErrInternal creates an RFC 7807 500 Internal Server Error problem details error.

func ErrNotFound

func ErrNotFound(detail string) *ProblemDetails

ErrNotFound creates an RFC 7807 404 Not Found problem details error.

func ErrRequestTimeout

func ErrRequestTimeout(detail string) *ProblemDetails

ErrRequestTimeout creates an RFC 7807 504 Gateway Timeout error.

func ErrUnauthorized

func ErrUnauthorized(detail string) *ProblemDetails

ErrUnauthorized creates an RFC 7807 401 Unauthorized problem details error.

func ErrValidation

func ErrValidation(violations []FieldViolation) *ProblemDetails

ErrValidation creates a structured RFC 7807 validation response.

func (*ProblemDetails) Error

func (p *ProblemDetails) Error() string

Error implements standard Go error interface.

type RouteMetadata

type RouteMetadata struct {
	Method      string
	Path        string
	Summary     string
	Description string
	Params      []string
}

RouteMetadata holds parameter and summary metadata for an endpoint.

type RouterGroup

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

RouterGroup organizes routes under a common path prefix and middleware set.

func (*RouterGroup) Any

func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc)

Any registers a route for all common HTTP methods.

func (*RouterGroup) DELETE

func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc)

DELETE registers a DELETE route.

func (*RouterGroup) GET

func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc)

GET registers a GET route.

func (*RouterGroup) Group

func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup

Group creates a new child route group with a path prefix and optional middleware.

func (*RouterGroup) HEAD

func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc)

HEAD registers a HEAD route.

func (*RouterGroup) Handle

func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc)

Handle registers a new request handler for a given HTTP method and path.

func (*RouterGroup) OPTIONS

func (group *RouterGroup) OPTIONS(relativePath string, handlers ...HandlerFunc)

OPTIONS registers an OPTIONS route.

func (*RouterGroup) PATCH

func (group *RouterGroup) PATCH(relativePath string, handlers ...HandlerFunc)

PATCH registers a PATCH route.

func (*RouterGroup) POST

func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc)

POST registers a POST route.

func (*RouterGroup) PUT

func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc)

PUT registers a PUT route.

func (*RouterGroup) RegisterModule

func (group *RouterGroup) RegisterModule(relativePath string, module Module)

RegisterModule mounts a domain module under a relative sub-route group.

func (*RouterGroup) Static

func (group *RouterGroup) Static(relativePath, root string)

Static serves static files from a root directory under a URL path prefix.

func (*RouterGroup) StaticEmbed

func (group *RouterGroup) StaticEmbed(relativePath string, embedFS embed.FS, optionalSubDir ...string)

StaticEmbed mounts an embedded filesystem (embed.FS) with zero-boilerplate automatic subfolder resolution (dist, build, static, public) and SPA index.html fallback.

func (*RouterGroup) StaticFS

func (group *RouterGroup) StaticFS(relativePath string, fsys fs.FS)

StaticFS serves embedded static files from an io/fs.FS filesystem (e.g. embed.FS) with SPA fallback routing to index.html.

func (*RouterGroup) Use

func (group *RouterGroup) Use(middlewares ...HandlerFunc)

Use appends middleware to the current route group.

Directories

Path Synopsis
Package audit emits structured security and business audit events through log/slog.
Package audit emits structured security and business audit events through log/slog.
Package auth provides password policy, signed token verification, session helpers, verified request identity, role checks, and attribute policies.
Package auth provides password policy, signed token verification, session helpers, verified request identity, role checks, and attribute policies.
Package bloom implements process-local probabilistic membership filters.
Package bloom implements process-local probabilistic membership filters.
Package cache defines cache stores and bounded memory and Redis implementations.
Package cache defines cache stores and bounded memory and Redis implementations.
cmd
doccheck command
Command doccheck verifies package and exported API documentation coverage.
Command doccheck verifies package and exported API documentation coverage.
gpp command
Package config loads typed application configuration from explicit sources.
Package config loads typed application configuration from explicit sources.
Package dbcore provides PostgreSQL and SQLite clients, transactions, migrations, typed queries, ORM conveniences, and stable database error classification.
Package dbcore provides PostgreSQL and SQLite clients, transactions, migrations, typed queries, ORM conveniences, and stable database error classification.
seed
Package seed provides development and test data generation.
Package seed provides development and test data generation.
Package di provides a small process-local dependency container.
Package di provides a small process-local dependency container.
examples
authentication
Package authentication demonstrates application-owned registration, login, account persistence, and hash migration using framework-owned auth mechanics.
Package authentication demonstrates application-owned registration, login, account persistence, and hash migration using framework-owned auth mechanics.
config_demo command
grpc_gateway/proto
Package proto declares the transport-neutral user contract for the gRPC example.
Package proto declares the transport-neutral user contract for the gRPC example.
grpc_gateway/services
Package services provides local and remote user-service example adapters.
Package services provides local and remote user-service example adapters.
hyper_scale_app command
load_test command
modular_monolith/modules/order
Package order demonstrates a self-contained modular-monolith order domain.
Package order demonstrates a self-contained modular-monolith order domain.
modular_monolith/modules/user
Package user demonstrates a self-contained modular-monolith user domain.
Package user demonstrates a self-contained modular-monolith user domain.
react_embedded command
realtime_demo command
secure_platform command
Package features provides process-local feature flag evaluation.
Package features provides process-local feature flag evaluation.
Package gpptest provides typed helpers for exercising gpp applications through httptest without opening network sockets.
Package gpptest provides typed helpers for exercising gpp applications through httptest without opening network sockets.
Package health provides bounded liveness and readiness HTTP handlers.
Package health provides bounded liveness and readiness HTTP handlers.
Package i18n provides language negotiation, translation catalogs, plurals, locale-aware number and money formatting, and localized date/time rendering.
Package i18n provides language negotiation, translation catalogs, plurals, locale-aware number and money formatting, and localized date/time rendering.
Package id generates UUID, UUIDv7, ULID, Snowflake, and prefixed identifiers.
Package id generates UUID, UUIDv7, ULID, Snowflake, and prefixed identifiers.
Package middleware provides gpp HTTP middleware for security, observability, recovery, request IDs, timeouts, rate limiting, idempotency, and protocol endpoints.
Package middleware provides gpp HTTP middleware for security, observability, recovery, request IDs, timeouts, rate limiting, idempotency, and protocol endpoints.
Package notify defines email and SMS provider contracts and bounded SendGrid and Twilio adapters.
Package notify defines email and SMS provider contracts and bounded SendGrid and Twilio adapters.
Package pubsub provides development-only in-memory publish/subscribe plus Redis and RabbitMQ adapters.
Package pubsub provides development-only in-memory publish/subscribe plus Redis and RabbitMQ adapters.
Package queue defines task publication, Kafka producer and consumer adapters, transactional outbox support, and process-local task tracking.
Package queue defines task publication, Kafka producer and consumer adapters, transactional outbox support, and process-local task tracking.
Package realtime provides Server-Sent Events and WebSocket handlers with bounded connection and message behavior.
Package realtime provides Server-Sent Events and WebSocket handlers with bounded connection and message behavior.
Package resilience provides circuit breaking, adaptive concurrency limiting, and retry helpers.
Package resilience provides circuit breaking, adaptive concurrency limiting, and retry helpers.
Package saga provides experimental process-local step coordination with reverse compensation.
Package saga provides experimental process-local step coordination with reverse compensation.
Package search defines schemas, normalized search requests, resource indexing, facets, and memory, PostgreSQL, and Elasticsearch backends.
Package search defines schemas, normalized search requests, resource indexing, facets, and memory, PostgreSQL, and Elasticsearch backends.
Package storage defines object storage operations and local and S3-backed implementations.
Package storage defines object storage operations and local and S3-backed implementations.
Package tenant extracts and installs tenant identity for request processing.
Package tenant extracts and installs tenant identity for request processing.
Package tracing configures OpenTelemetry trace export and lifecycle helpers.
Package tracing configures OpenTelemetry trace export and lifecycle helpers.
Package versioning negotiates API versions and emits deprecation and sunset metadata.
Package versioning negotiates API versions and emits deprecation and sunset metadata.

Jump to

Keyboard shortcuts

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