This guide walks you through combining all four GoKit packages —Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AndresGT/GoKit/llms.txt
Use this file to discover all available pages before exploring further.
logger, security/hash, security/jwt, and middleware — into a single, production-ready Gin application. By the end you will have a server with public routes anyone can call, protected routes that require a valid JWT, and admin-only routes that also enforce role-based access control.
Configure JWT
Call
jwt.Configure once at startup — before generating or validating any token. The Secret must be at least 32 characters; GoKit panics immediately on startup if it is not, so misconfiguration is caught before your server accepts any traffic.RefreshTokenDuration defaults to 7 days and RefreshSecret defaults to Secret — supply them explicitly if you want separate secrets for access and refresh tokens.Configure hashing
Call To switch to Argon2id later, change
hash.Configure to set your preferred algorithm and cost. This step is optional — the defaults (AlgBcrypt, cost 10) are production-ready — but calling it explicitly makes your configuration auditable.Algorithm to hash.AlgArgon2 and add an Argon2 params block. hash.Verify detects the algorithm from the stored hash prefix, so existing bcrypt hashes continue to work after the change.Initialize the logger
Call
logger.InitGlobal once. Subsequent calls are silently ignored (it is guarded by sync.Once), so it is safe to call from main without worrying about duplicate initialization.ServiceName is attached to every log entry as a field, which makes it easy to filter logs in aggregation tools when you run multiple services.Create the Gin router
Use
gin.New(), not gin.Default(). gin.Default() registers its own logger and recovery middleware, which would conflict with GoKit’s. GoKit provides both through its own middleware functions, giving you structured JSON-compatible logging and recovery that understand the GoKit context keys.Attach global middlewares in order
Register the four global middlewares in this specific order. Order is critical — see the Middleware ordering explained section below for the detailed rationale.
| Middleware | Preset | What it does |
|---|---|---|
DefaultRequestID | Trusts incoming X-Request-ID, generates UUID if absent | Injects request_id into Gin context and response header |
GinMiddleware | — | Creates per-request logger with request_id, method, path, IP |
DefaultCORS | AllowOrigins: ["*"], all common methods and headers | Adds CORS response headers; handles preflight OPTIONS |
DefaultRecovery | Stack trace enabled, error detail exposed | Catches panics and returns HTTP 500 |
In production, replace
DefaultCORS() with middleware.CORS(middleware.ProductionCORSConfig([]string{"https://your-app.com"})) and replace DefaultRecovery() with middleware.ProductionRecovery() to hide internal error details from clients.Register public routes
Create a route group and use
logger.RegisterRoutes to attach handlers. Passing Protected: false causes the logger to print the route with a → icon at startup so you can immediately see which routes are public.Register protected routes
Create a second group on the same Inside any protected handler, retrieve the authenticated user’s identity with
/api prefix and attach middleware.Auth. Use SkipPaths to list routes in the group that should be exempt — this is useful when a single group mixes public and private endpoints.middleware.GetUserID(c) and middleware.GetUserRole(c).Register admin-only routes
Chain
middleware.Auth and middleware.RequireRole on the same group. Auth validates the JWT and populates context keys; RequireRole then reads the role from context and aborts with 403 if it does not match.RequireRole accepts multiple roles: middleware.RequireRole("admin", "moderator") allows either.Complete main.go
The listing below combines every step above into a single, runnable file:Middleware ordering explained
The order
DefaultRequestID → GinMiddleware → DefaultCORS → DefaultRecovery is not arbitrary — each middleware depends on the one before it.- RequestID must run first. It reads the incoming
X-Request-IDheader, validates it (or generates a fresh UUID if absent), stores the value in the Gin context viac.Set("request_id", ...), and writes it to the response header. Every middleware and handler that follows can retrieve it withmiddleware.GetRequestID(c). - GinMiddleware must run second. It builds the per-request logger by reading the
X-Request-IDincoming request header along with the method, path, IP, and user-agent. Running it afterDefaultRequestIDensures the two middlewares operate on the same validated request ID — if a client sends no header,DefaultRequestIDgenerates one and both middlewares agree on the value for that request. - CORS must run before any handler that may return early. The CORS middleware sets
Access-Control-Allow-*headers and short-circuitsOPTIONSpreflight requests. If a handler or auth middleware aborts the request before CORS runs, the browser never receives the required headers and the request fails. - Recovery must come last among the global middlewares. It wraps the remainder of the chain in a
defer/recoverblock. If it were registered first, panics in the RequestID or GinMiddleware layers would not be caught. Registering it last means it catches panics from all subsequent middleware and every handler.