# HTTP context

> The *tinka.Ctx every handler and middleware receives: the request, the response, the request's ID and its dependencies.

This guide covers the HTTP context in Tinka. You will learn how to:

- Use the `*tinka.Ctx` a handler receives
- Pass it wherever a `context.Context` is expected
- Reach the request and the response writer when you need them
- Resolve request-scoped dependencies from the container

## Overview

Every request gets one **HTTP context**, a `*tinka.Ctx`, which the App passes to each middleware and to the handler. It holds everything about the request in one place: the incoming `*http.Request`, the response being built, the request's ID, and the request's dependencies. Handlers take it as their only argument, so their signatures stay the same however much of the request they use:

```go title="posts.go"
package main

import (
	"github.com/mucolabs/tinka"
)

type Post struct {
	ID    int64  `json:"id"`
	Title string `json:"title"`
}

func showPost(c *tinka.Ctx) (Post, error) {
	id, err := c.ParamInt("id")
	if err != nil {
		return Post{}, err
	}
	return Post{ID: id, Title: "Hello, Tinka"}, nil
}
```

A Ctx has methods for the [request](request.md), such as `Param`, `Query`, `IP` and `Accepts`, and for the [response](response.md), such as `Status` and `Header`. Those guides cover them.

## Pass it as a context

A Ctx is a `context.Context`: its deadline, cancellation and values are the request's. Pass it to the database, to HTTP clients and to your own code, and their work stops when the client disconnects or the request times out:

```go title="posts.go"
func (s *PostService) Find(ctx context.Context, id int64) (Post, error) {
	var p Post
	err := s.db.QueryRowContext(ctx, "SELECT id, title FROM posts WHERE id = $1", id).Scan(&p.ID, &p.Title)
	return p, err
}

func (h Posts) Show(c *tinka.Ctx) (Post, error) {
	id, err := c.ParamInt("id")
	if err != nil {
		return Post{}, err
	}
	return h.Service.Find(c, id)
}
```

Records you log with it carry the request's ID as `request_id`, as the [Logger](../digging-deeper/logger.md) guide shows. `c.ID()` returns the same ID, which the response also carries in its `X-Request-Id` header.

## Reach the request and the response writer

`c.Request()` returns the `*http.Request`, for anything the Ctx has no method for, such as request headers:

```go
	agent := c.Request().Header.Get("User-Agent")
```

`c.ResponseWriter()` returns the `http.ResponseWriter`, for a handler that writes the response itself, such as one that streams Server-Sent Events. Once anything is written, the handler's returned value is ignored. When a middleware replaces the request or the writer, as `tinka.Timeout` and compression middleware do, both methods return the replacement.

## Resolve request-scoped dependencies

Give the App your [dependency injection](../concepts/dependency-injection.md) container, and `c.Make` resolves from it through a resolver made for this request. A `Scoped` binding is built once per request, and can ask for the `*tinka.Ctx` itself:

```go title="main.go"
	container := di.New()
	container.Scoped(func(r *di.Resolver) (*Cart, error) {
		c := r.MustMake[*tinka.Ctx]()
		return carts.ForSession(c, c.Query("session"))
	})

	app := tinka.New(tinka.HTTPConfig{Container: container})
	app.Get("/cart", func(c *tinka.Ctx) (*Cart, error) {
		return c.Make[*Cart]()
	})
```

Resolve singletons at boot instead, and capture them in your handlers: a request that never calls `Make` pays nothing for the container.

:::warning
A Ctx belongs to one request. Keeping it after the handler returns, for example in a goroutine that outlives the request, reads a request that's already finished, whose context is canceled.

```go title="posts.go" del={1} ins={2-3}
	go notifyFollowers(c, post)
	ctx := context.WithoutCancel(c.Request().Context())
	go notifyFollowers(ctx, post)
```

Pass the background work what it needs, and a context detached from the request's with `context.WithoutCancel`: it keeps the request's values, such as its ID for the logs, without the Ctx or its cancellation.
:::

See also: [Request](request.md), [Response](response.md), [Middleware](middleware.md), [Dependency injection](../concepts/dependency-injection.md)
