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

# Built-in Middleware

> Use Lightning's built-in Logger and Recovery middleware to add request logging and panic recovery to your application.

Lightning ships two middleware functions out of the box: `Logger` for request logging and `Recovery` for panic recovery. You can register them individually or get both at once via `DefaultApp`.

## Logger

`Logger()` logs a single line for every completed request. It calls `ctx.Next()` first, so the log entry is written *after* the handler finishes, which means the status code and duration are accurate.

Each log line contains the following fields in order:

| Field          | Example           |
| -------------- | ----------------- |
| Remote address | `127.0.0.1:54321` |
| HTTP method    | `GET`             |
| Status code    | `200`             |
| Path           | `/api/users`      |
| Duration       | `3ms`             |
| User agent     | `curl/8.7.1`      |

### Register Logger

```go theme={null}
app.Use(lightning.Logger())
```

### Example output

```
[my-service] INFO 127.0.0.1:54321 GET 200 /api/users 3ms curl/8.7.1
```

## Recovery

`Recovery()` wraps the downstream handler chain in a `defer`/`recover` block. When a panic occurs, it:

1. Writes the panic value and full stack trace to `stderr`.
2. Responds to the client with `HTTP 500 Internal Server Error`.

### Register Recovery with the default handler

```go theme={null}
app.Use(lightning.Recovery())
```

### Register Recovery with a custom panic handler

Pass a single `HandlerFunc` to `Recovery` to replace the default 500 response with your own logic:

```go theme={null}
app.Use(lightning.Recovery(func(ctx *lightning.Context) {
    ctx.JSON(lightning.StatusInternalServerError, lightning.Map{
        "error": "something went wrong",
    })
}))
```

<Note>
  The panic value and stack trace are always written to `stderr` by `Recovery`, regardless of whether you supply a custom handler. Your custom handler only controls the HTTP response sent to the client.
</Note>

### Custom handler that logs to a structured logger

If your application uses a structured logger, you can capture the panic context and forward it before writing the response:

```go theme={null}
package main

import (
    "log/slog"
    "os"

    "github.com/go-labx/lightning"
)

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

    panicHandler := func(ctx *lightning.Context) {
        // At this point the panic has already been recovered by Lightning.
        // Log a structured error and return a JSON response.
        logger.Error("panic recovered",
            "method", ctx.Method,
            "path",   ctx.Path,
        )

        ctx.JSON(lightning.StatusInternalServerError, lightning.Map{
            "error":  "internal server error",
            "method": ctx.Method,
            "path":   ctx.Path,
        })
    }

    app := lightning.NewApp(&lightning.Config{AppName: "my-service"})
    app.Use(lightning.Logger())
    app.Use(lightning.Recovery(panicHandler))

    app.Get("/panic", func(ctx *lightning.Context) {
        panic("something unexpected")
    })

    app.Run(":8080")
}
```

## DefaultApp

`DefaultApp()` is the quickest way to get a fully configured application with both middleware already registered:

```go theme={null}
app := lightning.DefaultApp()
```

This is exactly equivalent to:

```go theme={null}
app := lightning.NewApp()
app.Use(lightning.Logger())
app.Use(lightning.Recovery())
```

## Composing middleware manually

When you need `DefaultApp`-style setup but also want a custom `Config`, use `NewApp` and call `app.Use` yourself:

```go theme={null}
package main

import "github.com/go-labx/lightning"

func main() {
    app := lightning.NewApp(&lightning.Config{
        AppName:     "orders-api",
        EnableDebug: true,
    })

    app.Use(lightning.Logger())
    app.Use(lightning.Recovery())

    app.Get("/orders", func(ctx *lightning.Context) {
        ctx.JSON(lightning.StatusOK, lightning.Map{"orders": []string{}})
    })

    app.Run(":8080")
}
```

<Tip>
  Middleware runs in the order you register it. Because `Logger` calls `ctx.Next()` before writing its log line, placing `Logger` before `Recovery` means the log entry correctly reflects any status code set by the panic handler. Register `Logger` first, then `Recovery`.
</Tip>
