Middlewares
Gleece provides middleware support for request processing.
Middleware events can be triggered at three distinct points:
- Operational Events
beforeOperation
: Executes before the operation/functionafterOperationSuccess
: Executes after successful operation completion
- Error Events
onInputValidationError
: Triggered when input validation failsonOperationError
: Triggered after operation failureonOutputValidationError
: Triggered when output validation fails (output validation is disabled by default, see Validating Response Payloads)
Each middleware receives the router's context (specific to the engine in use).
For error events, the middleware also receives the error instance.
Middlewares return a ctx
that will be used as the context in subsequent middlewares and route handlers
and a boolean value that determines the flow of execution:
true
: Continue with the normal execution flowfalse
: Abort execution (typically used when the response has been handled within the middleware)
Implementing Middleware
// For Gin
func MyMiddleware(ctx context.Context, ginCtx *gin.Context) (context.Context, bool) {
return ctx, true
}
// For Echo
func MyMiddleware(ctx context.Context, echoCtx echo.Context) (context.Context, bool) {
return ctx, true
}
// For Fiber
func MyMiddleware(ctx context.Context, fiberCtx *fiber.Ctx) (context.Context, bool) {
return ctx, true
}
// For Gorilla Mux & Chi
func MyMiddleware(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool) {
return ctx, true
}
And similarly for errors middlewares:
// For Gin
func MyErrorMiddleware(ctx context.Context, ginCtx *gin.Context, err error) (context.Context, bool) {
return ctx, true
}
// For Echo
func MyErrorMiddleware(ctx context.Context, echoCtx echo.Context, err error) (context.Context, bool) {
return ctx, true
}
// For Fiber
func MyErrorMiddleware(ctx context.Context, fiberCtx *fiber.Ctx, err error) (context.Context, bool) {
return ctx, true
}
// For Gorilla Mux & Chi
func MyErrorMiddleware(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) (context.Context, bool) {
return ctx, true
}
Registering Middleware
Use the generated code's RegisterMiddleware
/ RegisterErrorMiddleware
API to register your middleware functions.
Example:
package main
import (
"context"
"net/http"
"time"
gleeceRoutes "<package>"
"github.com/gopher-fleece/runtime"
"github.com/gin-gonic/gin"
)
const arriveTimeKey ctxKey = "arrive-time"
func LogBeforeOperationMiddleware(ctx context.Context, ginCtx *gin.Context) (context.Context, bool) {
println("Method:", ginCtx.Request.Method, "Path:", ctx.Request.URL.Path, "arrived")
ctx = context.WithValue(ctx, arriveTimeKey, time.Now())
return ctx, true
}
func LogAfterOperationSuccessMiddleware(ctx context.Context, ginCtx *gin.Context) (context.Context, bool) {
if arrive, ok := ctx.Value(arriveTimeKey).(time.Time); ok {
println("Method:", ginCtx.Request.Method, "Path:", ginCtx.Request.URL.Path, "completed in ", time.Since(arrive))
}
return ctx, true
}
func LogOnErrorMiddleware(ctx context.Context, ginCtx *gin.Context, err error) (context.Context, bool) {
println("Method:", ginCtx.Request.Method, "Path:", ginCtx.Request.URL.Path, "failed with error:", err.Error())
return ctx, true
}
func main() {
// Create a default Gin router
router := gin.Default()
// Register the middlewares
gleeceRoutes.RegisterMiddleware(runtime.BeforeOperation, LogBeforeOperationMiddleware)
gleeceRoutes.RegisterMiddleware(runtime.AfterOperationSuccess, LogAfterOperationSuccessMiddleware)
gleeceRoutes.RegisterErrorMiddleware(runtime.OnOperationError, LogOnErrorMiddleware)
// Register the routes from the generated code
gleeceRoutes.RegisterRoutes(router)
// Start the server on port 8080
router.Run("127.0.0.1:8080")
}
You can register any number of middleware functions. They will be executed in the order of registration.
When a middleware returns false
, it halts the execution chain, preventing any remaining middleware from running.