SRouter is an HTTP router for Go built on
julienschmidt/httprouter. It adds
recursive route groups, inherited route policy, typed request/response handlers,
authentication, rate limiting, metrics, structured logging, and graceful
shutdown support.
SRouter requires Go 1.27 or newer.
go get github.com/Suhaibinator/SRouterGo modules install the router and its dependencies automatically.
package main
import (
"log"
"net/http"
"github.com/Suhaibinator/SRouter/pkg/router"
)
func main() {
r := router.NewRouter[string, string](router.RouterConfig{
ServiceName: "hello-service",
}, router.RouterDependencies[string, string]{})
r.Route(router.RouteConfigBase{
Path: "/hello",
Methods: []router.HttpMethod{router.MethodGet},
Handler: func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"message":"hello"}`))
},
})
if err := r.Build(); err != nil {
log.Fatal(err)
}
log.Fatal(http.ListenAndServe(":8080", r))
}curl http://localhost:8080/helloAuthentication dependencies may be omitted when every route uses NoAuth, as
in this example. A nil logger is replaced by a production logger, with a no-op
fallback if logger creation fails.
Routes can be registered directly or beneath recursive groups. Each policy setting inherits independently from the router through outer groups, inner groups, and finally the route. With application-specific middleware and route definitions omitted, a tree looks like this:
api := r.Group("/api").
Timeout(3 * time.Second).
MaxBodySize(2 << 20).
Use(apiMiddleware)
v1 := api.Group("/v1").Auth(router.AuthRequired)
v1.Route(getUserRoute, createUserRoute)Root and group Route methods accept both standard RouteConfigBase values and
typed RouteConfig[Request, Response] values. Typed routes decode a configured
request source, optionally sanitize it, invoke a type-safe handler, and encode
the response.
Calling Build during startup is recommended. It validates the complete route
tree and freezes registration. The first request builds lazily if Build was
not called. A failed build is terminal for that router; later mutation panics.
- Radix-tree HTTP routing with path parameters
- Recursive groups with inherited authentication, timeout, body-size, and rate-limit policy
- Standard
http.HandlerFuncroutes and generic typed routes in the same tree - Request decoding from bodies, query parameters, or path parameters
- Global, group, and route middleware
- Built-in optional or required authentication
- Nonblocking, in-memory sliding-window rate limiting with lazy stale-key eviction
- Configurable client-IP and trusted-proxy handling
- CORS and preflight handling
- Structured HTTP errors and configurable request-summary logging
- Pluggable metrics, including a Prometheus adapter
- Trace IDs, graceful shutdown, WebSocket support, and context helpers
| Topic | Guide |
|---|---|
| Installation and first server | Getting started |
| Paths, methods, and parameters | Routing |
| Recursive groups and policy inheritance | Route groups |
| Typed handlers and request sources | Generic routes |
| Router and route configuration | Configuration reference |
| Middleware order and built-ins | Middleware |
| Authentication levels and providers | Authentication |
| Rate-limit strategies and buckets | Rate limiting |
| Client IP and proxy trust | IP configuration |
| Cross-origin requests | CORS |
| Request-scoped state | Context management |
| JSON, Protocol Buffers, and custom formats | Codecs |
| Registries, middleware, and Prometheus | Metrics |
| Trace IDs and request summaries | Logging |
| Structured handler errors | Error handling |
| Shutdown, deployment, and security | Production |
| Runnable programs | Examples |
- Route registration is frozen after
Buildor the first request. - Middleware order is recovery, automatic trace-ID injection, built-in authentication, configured rate limiting, global middleware, outer-to-inner group middleware, route middleware, timeout, then handler.
- Custom authentication added as global or group middleware runs after the configured rate limiter. User-based configured limits therefore require the built-in authentication stage to populate identity first.
TraceIDBufferSizecontrols trace-ID generation.EnableTraceLoggingindependently enables request-summary logs.- Optional build and config identity providers are sampled once per request and stored in the shared SRouter context.
- Proxy headers are trusted only when explicitly configured. Review the IP guide before enabling them because client-IP choice affects security and rate-limit keys.
- Generic routes default to the request body. Use the appropriate path/query
source or
Emptyfor bodyless requests.
All example programs are listed in docs/examples.md. Run an example as a package so that supporting files are included:
cd examples/simple
go run .go test ./...
go vet ./...
go fmt ./...CI enforces at least 80% aggregate coverage across the library packages.
SRouter is available under the MIT License.