# App

> The tinka.App type, its configuration, and everything it does for every request by default.

This guide covers the `tinka.App` type. You will learn how to:

- Create an App and configure it
- Register routes with its methods
- Know what every request gets by default
- Know the limits on request bodies

## Overview

`tinka.App` is the HTTP side of a Tinka application. It's an `http.Handler` with a [Router](../guides/basics/routing.md), one place where errors become responses, and safe defaults that need no configuration.

## Create an App

`tinka.New(cfg)` returns an App. The zero `HTTPConfig` is ready to use.

::::options

:::option{name="Logger" type="*slog.Logger"}
Receives one record per request and every unexpected error. Defaults to `slog.Default()`.
:::

::::

## Methods

::::options

:::option{name="Get, Post, Put, Patch, Delete" type="func(pattern string, h tinka.HandlerFunc)"}
Register a handler for one method. `Get` also answers `HEAD`.
:::

:::option{name="Handle" type="func(method, pattern string, h http.Handler)"}
Register any `http.Handler`. An empty method matches every method.
:::

:::option{name="Route" type="func(prefix string, fn func(r *tinka.Router))"}
Register routes under a prefix. Inside `fn`, `"/"` is the prefix itself.
:::

:::option{name="Group" type="func(fn func(r *tinka.Router))"}
Scope middleware added with `Use` to the routes inside `fn`.
:::

:::option{name="Use" type="func(mw ...tinka.Middleware)"}
Apply middleware to the routes registered after it. Panics if routes already exist on the router.
:::

:::option{name="With" type="func(mw ...tinka.Middleware) *tinka.Router"}
Return a router that applies `mw` to the routes registered on it.
:::

:::option{name="OnError" type="func(fn func(w http.ResponseWriter, r *http.Request, e *tinka.Error) error)"}
Replace how errors render. If `fn` returns an error, the default problem details are sent.
:::

::::

## What every request gets

These apply to every request, before and after routing.

::::options

:::option{name="Request ID" type="X-Request-Id"}
Every request gets an ID, sent back in the `X-Request-Id` header and included in its log records and error responses. A client's own `X-Request-Id` is kept when it's at most 64 characters of letters, digits, `-`, `_`, `.` and `:`. Anything else is replaced with 26 random characters, so a client cannot inject text into the logs.
:::

:::option{name="Security headers" type="response headers"}
Responses carry `X-Content-Type-Options: nosniff` and `Referrer-Policy: strict-origin-when-cross-origin`. A handler can override either.
:::

:::option{name="Cross-origin protection" type="403 cross_origin"}
Browser requests that change data (`POST`, `PUT`, `PATCH`, `DELETE`) from another origin are refused, using `http.CrossOriginProtection`. This blocks cross-site request forgery without tokens. Safe methods and non-browser clients are always allowed.
:::

:::option{name="Panic recovery" type="500 internal"}
A panic in a handler is logged with its stack and answered with a `500`. The App keeps serving.
:::

:::option{name="Access log" type="slog record"}
One `request` record per request, at level `INFO`, with `request_id`, `method`, `path`, `status` and `took`. When a handler stops because its client disconnected, the record has status `499` and nothing is written back.
:::

:::option{name="Unmatched requests" type="404, 405, 308"}
A path with no route gets a `404`. A path whose routes don't accept the method gets a `405` with an `Allow` header. A `GET` or `HEAD` with a trailing slash gets a `308` to the same path without it, when that path has a route.
:::

:::option{name="Error responses" type="application/problem+json"}
Errors render as RFC 9457 problem details with `title`, `status`, `detail`, `code`, and when present `hint`, `fields` and `request_id`. Browsers that ask for HTML get an HTML page. Responses carry `Cache-Control: no-store`.
:::

::::

## Request bodies

[`tinka.Decode`](../guides/basics/body-parser.md) reads at most `tinka.MaxBodyBytes` (1 MiB) and waits at most 30s for the body to arrive. Requests without a body pay nothing for these limits.

See also: [Routing](../guides/basics/routing.md), [Exception handling](../guides/basics/exception-handling.md)
