-
Notifications
You must be signed in to change notification settings - Fork 0
Home
An extension-based HTTP framework for Go. A trie router, a lifecycle, a DI container, an event bus, and a set of extensions that plug into all of it without depending on any of it.
go get github.com/kryovyx/rexRequires Go 1.27+.
package main
import (
"github.com/kryovyx/rex"
"github.com/kryovyx/rex/route"
)
func main() {
app := rex.New()
if err := app.RegisterRoute(route.New("GET", "/hello", func(ctx route.Context) {
_ = ctx.Text(200, "Hello, World!")
})); err != nil {
panic(err)
}
if err := app.Run(); err != nil { // blocks until SIGINT/SIGTERM
panic(err)
}
}New() collects. Run() builds.
New creates the container, the event bus and the logger, applies your options,
and returns. It creates no routers, runs no extension hooks, binds nothing, and
cannot fail.
Run freezes the configuration, creates the routers, runs the extension hooks,
composes every middleware chain, builds and freezes every route table,
validates, binds the listeners synchronously, and only then reports readiness.
Two consequences you will feel immediately:
-
Declaration order does not matter. Middleware before its router, a route
before the router it names, configuration after everything — all fine, because
nothing is resolved until
Run. -
Nothing may be registered after
Run. The route table is published by atomic swap and read without a lock, so there is nowhere safe to add to it. A late registration is refused withErrRouterFrozen, not silently dropped.
See Lifecycle.
| Routing | trie router with {param} and * segments, real 404/405 distinction, router-answered OPTIONS
|
| Routers and Listeners | any number of named listeners — public API on :8080, admin on :9090, metrics on :9091
|
| Middleware | a fixed priority scale, per-route and per-router factories, chains composed once at build |
| Dependency Injection |
dix container, with a scope per request |
| Events | typed router events on a non-blocking bus |
| Logging |
log/slog-backed, structured, swappable |
| Errors on the Wire | RFC 9457 problem documents, from the framework and every extension |
| TLS and Listener Limits | per-handshake certificates, mTLS, timeouts and body caps that are actually set |
| Graceful Shutdown | signal-driven, bounded, runs exactly once |
Extensions depend on rextension — a contract module with no dependencies —
not on rex. Adding one to your application never adds the framework twice.
| Module | Does |
|---|---|
| rextension | the contract extension authors build against |
| rextension-cors | Cross-Origin Resource Sharing |
| rextension-health | liveness, readiness, dependency gating |
| rextension-metric | Prometheus / OpenMetrics |
| rextension-openapi | OpenAPI 3.1 generation |
| rextension-ratelimit | global, per-router and per-endpoint limits |
| rextension-security | authentication, roles, scopes, CSRF |
| rextension-swagger | Swagger UI |
| rextension-validation | request and response validation |
app := rex.New(
cors.WithCORS(corsCfg),
security.WithSecurity(secCfg),
health.WithHealth(nil),
metric.WithMetrics(nil),
openapi.WithOpenAPI(apiCfg),
swagger.WithSwagger(nil),
)See Extensions for what each one attaches, and in what order.
Pre-1.0 (alpha). Interfaces may change between minor versions, and the project is not open to external contributions yet.
If you are upgrading from v0.2.1, read the workspace's MIGRATION-v0.3.0.md
first — v0.3.0 is one architectural change (the frozen route table) with many
consequences, and it fixes four extensions that were silently doing nothing.
rex — Restful Extended eXperience · MIT · © 2026 Kryovyx · pre-1.0 (alpha), interfaces may change
Getting started
Core
Operating
Ecosystem