> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Middleware Basics

> Learn how to create and use middleware functions.

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:

```go theme={null}
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:

* [http://localhost:8080/](http://localhost:8080/)
  Response:
  `Home page - no auth required`
  The logger middleware runs for this route and prints something like:
  `INFO request completed method=GET path=/ status=200 duration=1.2ms`

* [http://localhost:8080/dashboard](http://localhost:8080/dashboard)
  Response:
  `Unauthorized`

* Add a token to simulate an authenticated request:
  [http://localhost:8080/dashboard?token=secret](http://localhost:8080/dashboard?token=secret)
  Response:
  `Welcome to your dashboard`

### 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 Middleware        | Description                                       | Example                                       |
| ------------------------- | ------------------------------------------------- | --------------------------------------------- |
| Global middleware         | Runs for every route, used for logging or errors. | `app.Use(logger)`                             |
| Route-specific middleware | Runs only on certain routes.                      | `app.With(auth).Get("/dashboard", dashboard)` |
| Middleware chain          | Wraps 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:

```go theme={null}
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:

```go theme={null}
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](./009-error-handling-recover) to learn how to handle panics and send friendly error messages.
