> ## 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.

# Request Handling

> Read URL params, query strings, request bodies, headers, and cookies from incoming HTTP requests.

Lightning gives you a clean `Context` API to access every part of an incoming request. All methods live on the `*Context` value passed to your handler.

## URL Parameters

Define dynamic segments in your route pattern with a `:` prefix. Read them at runtime with `ctx.Param()`.

```go theme={null}
app.Get("/users/:id", func(ctx *lightning.Context) {
    id := ctx.Param("id") // string

    // Typed conversions
    idInt, err := ctx.ParamInt("id")
    if err != nil {
        ctx.JSONError(lightning.StatusBadRequest, "invalid id")
        return
    }

    ctx.JSON(lightning.StatusOK, lightning.Map{"id": idInt})
})
```

Typed param helpers return `(T, error)` so you can handle malformed values explicitly:

| Method                  | Return type        |
| ----------------------- | ------------------ |
| `ctx.ParamInt(key)`     | `(int, error)`     |
| `ctx.ParamInt64(key)`   | `(int64, error)`   |
| `ctx.ParamUInt(key)`    | `(uint, error)`    |
| `ctx.ParamUInt64(key)`  | `(uint64, error)`  |
| `ctx.ParamFloat32(key)` | `(float32, error)` |
| `ctx.ParamFloat64(key)` | `(float64, error)` |

Use `ctx.Params()` to get all URL parameters as `map[string]string` at once.

## Query Parameters

Read query string values with `ctx.Query()` for strings or the typed helpers for numeric and boolean values.

```go theme={null}
app.Get("/search", func(ctx *lightning.Context) {
    q := ctx.Query("q") // string, empty string if absent

    page, err := ctx.QueryInt("page")
    if err != nil {
        ctx.JSONError(lightning.StatusBadRequest, "page must be an integer")
        return
    }

    active, err := ctx.QueryBool("active")
    if err != nil {
        ctx.JSONError(lightning.StatusBadRequest, "active must be a boolean")
        return
    }

    ctx.JSON(lightning.StatusOK, lightning.Map{
        "q":      q,
        "page":   page,
        "active": active,
    })
})
```

All typed query helpers return zero values (not errors) when the key is absent, and return an error only when the value is present but cannot be parsed.

Full set of typed query helpers:

| Method                  | Return type        |
| ----------------------- | ------------------ |
| `ctx.QueryInt(key)`     | `(int, error)`     |
| `ctx.QueryInt8(key)`    | `(int8, error)`    |
| `ctx.QueryInt32(key)`   | `(int32, error)`   |
| `ctx.QueryInt64(key)`   | `(int64, error)`   |
| `ctx.QueryUInt(key)`    | `(uint, error)`    |
| `ctx.QueryUInt8(key)`   | `(uint8, error)`   |
| `ctx.QueryUInt32(key)`  | `(uint32, error)`  |
| `ctx.QueryUInt64(key)`  | `(uint64, error)`  |
| `ctx.QueryFloat32(key)` | `(float32, error)` |
| `ctx.QueryFloat64(key)` | `(float64, error)` |
| `ctx.QueryBool(key)`    | `(bool, error)`    |

Use `ctx.Queries()` to get all query parameters as `map[string][]string`.

## Request Body

### JSON body

Use `ctx.JSONBody(&v)` to decode the request body into a struct. Pass `true` as the second argument to also validate the struct using [go-playground/validator](https://github.com/go-playground/validator) struct tags.

```go theme={null}
type CreateUserRequest struct {
    Name     string `json:"name"     validate:"required"`
    Email    string `json:"email"    validate:"required,email"`
    Password string `json:"password" validate:"required,min=8,max=32"`
}

app.Post("/users", func(ctx *lightning.Context) {
    var req CreateUserRequest
    if err := ctx.JSONBody(&req, true); err != nil {
        ctx.Fail(-1, err.Error())
        return
    }

    ctx.Success(req)
})
```

Omit the second argument (or pass `false`) to skip validation and decode only:

```go theme={null}
err := ctx.JSONBody(&req)        // decode, no validation
err := ctx.JSONBody(&req, true)  // decode + validate
```

### Raw and string body

```go theme={null}
app.Post("/webhook", func(ctx *lightning.Context) {
    raw := ctx.RawBody()    // []byte
    str := ctx.StringBody() // string

    ctx.Text(lightning.StatusOK, "received")
})
```

## Headers

Read a single request header by name with `ctx.Header()`. Header names are case-insensitive.

```go theme={null}
app.Get("/protected", func(ctx *lightning.Context) {
    auth := ctx.Header("Authorization")
    if auth == "" {
        ctx.JSONError(lightning.StatusUnauthorized, "missing authorization header")
        return
    }

    ctx.JSON(lightning.StatusOK, lightning.Map{"token": auth})
})
```

Use `ctx.Headers()` to get all request headers as `map[string]string`.

## Cookies

Read a single cookie by name with `ctx.Cookie()`. It returns `*fasthttp.Cookie` (or `nil` if the cookie is not present).

```go theme={null}
app.Get("/dashboard", func(ctx *lightning.Context) {
    session := ctx.Cookie("session_id")
    if session == nil {
        ctx.JSONError(lightning.StatusUnauthorized, "no session")
        return
    }

    // cookie.Key() and cookie.Value() return []byte
    ctx.JSON(lightning.StatusOK, lightning.Map{
        "session": string(session.Value()),
    })
})
```

Use `ctx.Cookies()` to iterate over all cookies in the request:

```go theme={null}
cookies := ctx.Cookies() // []*fasthttp.Cookie
for _, c := range cookies {
    fmt.Println(string(c.Key()), string(c.Value()))
}
```

## Complete Example: POST Handler with JSON Validation

The following handler parses a JSON body, validates it, and returns a structured response.

```go theme={null}
package main

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

type RegisterRequest struct {
    Name     string `json:"name"     validate:"required"`
    Email    string `json:"email"    validate:"required,email"`
    Password string `json:"password" validate:"required,min=8,max=32"`
}

func main() {
    app := lightning.DefaultApp()

    app.Post("/register", func(ctx *lightning.Context) {
        var req RegisterRequest

        // Decode the JSON body and run validator struct tags
        if err := ctx.JSONBody(&req, true); err != nil {
            ctx.Fail(-1, err.Error())
            return
        }

        // Use the validated data
        ctx.Success(lightning.Map{
            "name":  req.Name,
            "email": req.Email,
        })
    })

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

**Example request:**

```bash theme={null}
curl -X POST http://localhost:8080/register \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","email":"alice@example.com","password":"secret123"}'
```

**Example response:**

```json theme={null}
{
  "code": 0,
  "message": "ok",
  "data": {
    "name": "Alice",
    "email": "alice@example.com"
  }
}
```

If validation fails, `ctx.JSONBody` returns the first validation error as a Go error, and `ctx.Fail(-1, err.Error())` sends it back to the client.
