# Limit request bodies

Every request body is capped at `settings.MaxBodyBytes` (1 MiB by default,
`CICADEL_MAX_BODY_BYTES`). Raise the cap for one route, such as an upload, and
keep the small default everywhere else.

## Upload routes raise their own limit

`forms/upload` uses the upload's `Config.MaxBytes` as the request's limit. No
other change is needed:

```go
upload.Middleware(func(*http.Request) (upload.Config, error) {
    return upload.Config{
        MaxBytes: 12 << 20, // a 10 MB file plus the form around it
        Fields:   []upload.Field{{Name: "slip", MaxBytes: 10 << 20}},
    }, nil
})
```

Each field keeps its own `Field.MaxBytes`.

## Other routes: `bodylimit.Limit`

Wrap a route handler, or add the middleware to `App.Middleware` for every route
of an app:

```go
urls.Route{
    Method:  "POST",
    Path:    "/imports",
    Name:    "imports:create",
    Handler: bodylimit.Limit(50 << 20)(http.HandlerFunc(createImport)),
}
```

`Limit` can raise or lower the default. Inside a handler, call
`bodylimit.Set(w, r, n)` instead.

## Rules

- A limit can change only before the body is first read. After that, `Set`
  returns `bodylimit.ErrBodyRead` and `Limit` answers 500, because the route's
  limit could not be applied.
- Reading past the limit fails with `*http.MaxBytesError`, and the server closes
  the connection after the response. Answer with 413 or a form error.
- CSRF middleware parses URL-encoded forms, so its reads count against the
  route's limit. Multipart bodies are not read by CSRF.
- `contrib/accounts` no longer caps every route under `Browser.Middleware` at
  8 KiB. The account pages keep their own 8 KiB bound.
- Handlers served outside a `cicadel.Application` have no adjustable limit.
  `Set` then wraps the body with `http.MaxBytesReader`, which can only lower an
  existing limit. Call `bodylimit.Apply` to install one.

Keep `MaxBodyBytes` small. Every form and JSON endpoint accepts that much
without asking.
