go-bootstrapify-modules
Reusable modules for the go-bootstrapify bootstrapper framework.
Overview
go-bootstrapify-modules provides a collection of commonly used modules that integrate seamlessly with the go-bootstrapify dependency injection framework. These modules handle typical web application concerns like HTTP routing, database connectivity, logging, and health checks.
Modules
HTTP Module
- Gin framework integration
- Correlation ID middleware
- Request logging middleware
- Error response handling middleware
- Context key utilities
- Route definition with groups, policies and typed path params (see HTTP routes)
- Route exporters, including a Traefik v3 dynamic config file exporter
PostgreSQL Module
- pgx/v5 driver integration
- Database executor with querier interface
- Query builder with filtering, ordering, and pagination
- Database migration support (golang-migrate)
Logger Module
- zerolog integration
- Structured logging support
Health Module
- Health check endpoints
- Service health monitoring
Installation
go get gitlab.com/bitval/go-bootstrapify-modules
Requirements
Usage
Import the modules you need and register them with your go-bootstrapify application:
import (
"gitlab.com/bitval/go-bootstrapify"
"gitlab.com/bitval/go-bootstrapify-modules/http"
"gitlab.com/bitval/go-bootstrapify-modules/logger"
"gitlab.com/bitval/go-bootstrapify-modules/postgresdb"
"gitlab.com/bitval/go-bootstrapify-modules/health"
)
func main() {
app := bootstrapify.New()
// Register modules
app.Register(logger.Module())
app.Register(postgresdb.Module())
app.Register(http.Module())
app.Register(health.Module())
app.Run()
}
HTTP routes
Routes are defined with DefineRoutes, after Configure:
import (
httpModule "gitlab.com/bitval/go-bootstrapify-modules/http"
"gitlab.com/bitval/go-bootstrapify-modules/http/route"
"gitlab.com/bitval/go-bootstrapify-modules/http/traefik"
)
m := httpModule.New()
err := m.Configure(
httpModule.WithPolicy("protected", checkAuth),
httpModule.WithPolicy("admin", checkAuth, requireAdmin),
httpModule.WithRouteExporter(traefik.NewFileExporter(
traefik.WithOutputFile("/etc/traefik/dynamic/setups.yml"),
traefik.WithRouterPrefix("setups"),
traefik.WithService("setups-api"),
traefik.WithHost("api.example.com"),
traefik.WithEntryPoints("websecure"),
traefik.WithCertResolver("letsencrypt"),
traefik.WithDefaultMiddlewares("cors@file"),
traefik.WithPolicyMiddlewares("protected", "forward-auth@file"),
traefik.WithPolicyMiddlewares("admin", "forward-auth@file", "admin-ipallowlist@file"),
)),
)
err = m.DefineRoutes("/api/v1", func(g *route.Group) {
setups := g.Group("/setups").Param("setup_id", route.UUID)
setups.GET("", listSetups)
setups.GET("/:setup_id", getSetup)
setups.POST("/:setup_id/rate/:vote", rateSetup).
Policy("protected").
Param("vote", route.OneOf("up", "down"))
setups.DELETE("/:setup_id", deleteSetup).Policy("protected", "admin")
g.Internal("/internal").GET("/status", status)
})
- Groups share a path prefix.
Group(prefix, mw...) takes plain gin middleware that only runs in the service. Middleware, policies and params set on a group apply to every route in it, whether set before or after the routes.
- Policies are named bundles of middleware registered with
WithPolicy, executed in the given order by every group or route that applies them with Policy(name). A route exporter may map the same name to proxy middleware, which the request passes through on the proxy first. Unknown policy names fail DefineRoutes.
- Params are constrained with
Param(name, pattern) using route.UUID, route.Numeric, route.OneOf(values...) or route.Regex(expr). A request with a non-matching param gets a 404. A pattern must not be able to match / (use [^/] rather than .), must not contain ^/$ anchors, and a *name catch-all can't have a pattern.
- Internal groups are served but left out of exported proxy configuration.
- Handlers run in the order: group middleware, param check, policy middleware, route handlers.
DefineRoutes can be called more than once. Each call is validated against all routes defined so far (duplicate and ambiguous routes are rejected), and exporters always receive the full set.
The Traefik exporter writes one router per route: static paths use Path at priority 200, paths with params use an anchored PathRegexp at priority 100, and each router gets the default middlewares followed by the route's policy middlewares. The file is replaced atomically on every export. Without WithOutputFile (or with an empty path) the exporter does nothing, so a service can switch to DefineRoutes before its proxy configuration moves to the generated file.
Route, WithRoute, RegisterRoute and RegisterRoutes still work but are deprecated in favour of DefineRoutes.
License
MIT License - see LICENSE for details
Status
This project is in early alpha stage and under active development.