--- title: go-api description: Gin-based REST framework with OpenAPI generation, middleware composition, and SDK codegen for the Lethean Go ecosystem. --- # go-api **Module path:** `forge.lthn.ai/core/go-api` **Language:** Go 1.26 **Licence:** EUPL-1.2 go-api is a REST framework built on top of [Gin](https://github.com/gin-gonic/gin). It provides an `Engine` that subsystems plug into via the `RouteGroup` interface. Each ecosystem package (go-ai, go-ml, go-rag, and others) registers its own route group, and go-api handles the HTTP plumbing: middleware composition, response envelopes, WebSocket and SSE integration, GraphQL hosting, Authentik identity, OpenAPI 3.1 specification generation, and client SDK codegen. go-api is a library. It has no `main` package and produces no binary on its own. Callers construct an `Engine`, register route groups, and call `Serve()`. --- ## Quick Start ```go package main import ( "context" "os/signal" "syscall" api "forge.lthn.ai/core/go-api" ) func main() { engine, _ := api.New( api.WithAddr(":8080"), api.WithBearerAuth("my-secret-token"), api.WithCORS("*"), api.WithRequestID(), api.WithSecure(), api.WithSlog(nil), api.WithSwagger("My API", "A service description", "1.0.0"), ) engine.Register(myRoutes) // any RouteGroup implementation ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() _ = engine.Serve(ctx) // blocks until context is cancelled, then shuts down gracefully } ``` The default listen address is `:8080`. A built-in `GET /health` endpoint is always present. Every feature beyond panic recovery requires an explicit `With*()` option. --- ## Implementing a RouteGroup Any type that satisfies the `RouteGroup` interface can register endpoints: ```go type Routes struct{ service *mypackage.Service } func (r *Routes) Name() string { return "mypackage" } func (r *Routes) BasePath() string { return "/v1/mypackage" } func (r *Routes) RegisterRoutes(rg *gin.RouterGroup) { rg.GET("/items", r.listItems) rg.POST("/items", r.createItem) } func (r *Routes) listItems(c *gin.Context) { items, _ := r.service.List(c.Request.Context()) c.JSON(200, api.OK(items)) } ``` Register with the engine: ```go engine.Register(&Routes{service: svc}) ``` --- ## Package Layout | File | Purpose | |------|---------| | `api.go` | `Engine` struct, `New()`, `build()`, `Serve()`, `Handler()`, `Channels()` | | `options.go` | All `With*()` option functions (25 options) | | `group.go` | `RouteGroup`, `StreamGroup`, `DescribableGroup` interfaces; `RouteDescription` | | `response.go` | `Response[T]`, `Error`, `Meta`, `OK()`, `Fail()`, `FailWithDetails()`, `Paginated()` | | `middleware.go` | `bearerAuthMiddleware()`, `requestIDMiddleware()` | | `authentik.go` | `AuthentikUser`, `AuthentikConfig`, `GetUser()`, `RequireAuth()`, `RequireGroup()` | | `websocket.go` | `wrapWSHandler()` helper | | `sse.go` | `SSEBroker`, `NewSSEBroker()`, `Publish()`, `Handler()`, `Drain()`, `ClientCount()` | | `cache.go` | `cacheStore`, `cacheEntry`, `cacheWriter`, `cacheMiddleware()` | | `brotli.go` | `brotliHandler`, `newBrotliHandler()`; compression level constants | | `graphql.go` | `graphqlConfig`, `GraphQLOption`, `WithPlayground()`, `WithGraphQLPath()`, `mountGraphQL()` | | `i18n.go` | `I18nConfig`, `WithI18n()`, `i18nMiddleware()`, `GetLocale()`, `GetMessage()` | | `tracing.go` | `WithTracing()`, `NewTracerProvider()` | | `swagger.go` | `swaggerSpec`, `registerSwagger()`; sequence counter for multi-instance safety | | `openapi.go` | `SpecBuilder`, `Build()`, `buildPaths()`, `buildTags()`, `envelopeSchema()` | | `export.go` | `ExportSpec()`, `ExportSpecToFile()` | | `bridge.go` | `ToolDescriptor`, `ToolBridge`, `NewToolBridge()`, `Add()`, `Describe()`, `Tools()` | | `codegen.go` | `SDKGenerator`, `Generate()`, `Available()`, `SupportedLanguages()` | | `cmd/api/` | CLI subcommands: `core api spec` and `core api sdk` | --- ## Dependencies ### Direct | Module | Role | |--------|------| | `github.com/gin-gonic/gin` | HTTP router and middleware engine | | `github.com/gin-contrib/cors` | CORS policy middleware | | `github.com/gin-contrib/secure` | Security headers (HSTS, X-Frame-Options, nosniff) | | `github.com/gin-contrib/gzip` | Gzip response compression | | `github.com/gin-contrib/slog` | Structured request logging via `log/slog` | | `github.com/gin-contrib/timeout` | Per-request deadline enforcement | | `github.com/gin-contrib/static` | Static file serving | | `github.com/gin-contrib/sessions` | Cookie-backed server sessions | | `github.com/gin-contrib/authz` | Casbin policy-based authorisation | | `github.com/gin-contrib/httpsign` | HTTP Signatures verification | | `github.com/gin-contrib/location/v2` | Reverse proxy header detection | | `github.com/gin-contrib/pprof` | Go profiling endpoints | | `github.com/gin-contrib/expvar` | Runtime metrics endpoint | | `github.com/casbin/casbin/v2` | Policy-based access control engine | | `github.com/coreos/go-oidc/v3` | OIDC provider discovery and JWT validation | | `github.com/andybalholm/brotli` | Brotli compression | | `github.com/gorilla/websocket` | WebSocket upgrade support | | `github.com/swaggo/gin-swagger` | Swagger UI handler | | `github.com/swaggo/files` | Swagger UI static assets | | `github.com/swaggo/swag` | Swagger spec registry | | `github.com/99designs/gqlgen` | GraphQL schema execution (gqlgen) | | `go.opentelemetry.io/otel` | OpenTelemetry tracing SDK | | `go.opentelemetry.io/contrib/.../otelgin` | OpenTelemetry Gin instrumentation | | `golang.org/x/text` | BCP 47 language tag matching | | `gopkg.in/yaml.v3` | YAML export of OpenAPI specs | | `forge.lthn.ai/core/cli` | CLI command registration (for `cmd/api/` subcommands) | ### Ecosystem position go-api sits at the base of the Lethean HTTP stack. It has no imports from other Lethean ecosystem modules (beyond `core/cli` for the CLI subcommands). Other packages import go-api to expose their functionality as REST endpoints: ``` Application main / Core CLI | v go-api Engine <-- this module | | | | | +-- OpenAPI spec --> SDKGenerator --> openapi-generator-cli | +-- ToolBridge --> go-ai / go-ml / go-rag route groups +-- RouteGroups ----------> any package implementing RouteGroup ``` --- ## Further Reading - [Architecture](architecture.md) -- internals, key types, data flow, middleware stack - [Development](development.md) -- building, testing, contributing, coding standards