Skip to main content
In this lesson, you will learn what middleware is and how to use it in Mizu. Middleware is a function that runs before or after your main handler. It can log requests, check authentication, handle errors, or modify responses, all without changing your route logic. Mizu middleware follows Go’s net/http design, so you can use standard handlers or write your own in a simple, composable way.

Code

Create a file named main.go and add this code:
package main

import (
	"log"
	"net/http"
	"time"

	"github.com/go-mizu/mizu"
)

// Simple logging middleware
func logger(next mizu.Handler) mizu.Handler {
	return func(c *mizu.Ctx) error {
		start := time.Now()
		err := next(c)
		c.Logger().Info("request completed",
			"method", c.Request().Method,
			"path", c.Request().URL.Path,
			"status", c.StatusCode(),
			"duration", time.Since(start),
		)
		return err
	}
}

// Authentication middleware example
func auth(next mizu.Handler) mizu.Handler {
	return func(c *mizu.Ctx) error {
		token := c.Query("token")
		if token != "secret" {
			return c.Text(http.StatusUnauthorized, "Unauthorized")
		}
		return next(c)
	}
}

// Protected route
func dashboard(c *mizu.Ctx) error {
	return c.Text(http.StatusOK, "Welcome to your dashboard")
}

// Public route
func home(c *mizu.Ctx) error {
	return c.Text(http.StatusOK, "Home page - no auth required")
}

func main() {
	app := mizu.New()

	// Global middleware
	app.Use(logger)

	// Public route
	app.Get("/", home)

	// Protected route with route-specific middleware
	app.With(auth).Get("/dashboard", dashboard)

	if err := app.Listen(":8080"); err != nil {
		log.Fatal(err)
	}
}

Run

Start your server:
go run .
Then open your browser and try these routes:

How it works

Middleware in Mizu is a function that takes a mizu.Handler and returns another mizu.Handler. Each middleware can decide whether to continue to the next handler or stop early.
Type of MiddlewareDescriptionExample
Global middlewareRuns for every route, used for logging or errors.app.Use(logger)
Route-specific middlewareRuns only on certain routes.app.With(auth).Get("/dashboard", dashboard)
Middleware chainWraps multiple layers around your handler.Logging → Auth → Handler
Every middleware gets the same *mizu.Ctx object and can read or modify the request and response. The next(c) call runs the next function in the chain.

Try something new

Add a timing middleware to measure how long each request takes:
func timing(next mizu.Handler) mizu.Handler {
	return func(c *mizu.Ctx) error {
		start := time.Now()
		err := next(c)
		elapsed := time.Since(start)
		return c.Text(http.StatusOK, "Took "+elapsed.String())
	}
}
Apply it to a specific route:
app.With(timing).Get("/slow", func(c *mizu.Ctx) error {
	time.Sleep(2 * time.Second)
	return c.Text(http.StatusOK, "Finished slow task")
})
Middleware helps you keep your handlers clean while layering shared logic such as authentication, logging, metrics, and caching. Next, continue to Error Handling and Recover to learn how to handle panics and send friendly error messages.