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

# Request Lifecycle

Understanding how a request travels through a Copper application makes everything else in these docs feel less magical. This page follows one request from the socket to the response.

### Accepting the Request

`copper.New()` builds the app container, and `app.Start(server)` runs `chttp.Server`, which listens on the configured port (5901 in generated projects). Every request that arrives is handled by a single `http.Handler` assembled at startup in `pkg/app/handler.go`:

```go pkg/app/handler.go theme={null}
func NewHTTPHandler(p NewHTTPHandlerParams) http.Handler {
	return chttp.NewHandler(chttp.NewHandlerParams{
		Routers: []chttp.Router{
			p.Rockets,
		},
		GlobalMiddlewares: []chttp.Middleware{
			chttp.SetRequestIDInCtxMiddleware(),
			p.DatabaseTxMW,
			p.RequestLoggerMW,
		},
		Logger: p.Logger,
	})
}
```

This is the one place where your application's routers and global middlewares come together. Since the handler is built by [dependency injection](/architecture/dependency-injection), adding a router means adding a field, nothing more.

### Matching the Route

Copper collects every route from every router and sorts them automatically, so the most specific route wins regardless of declaration order. To learn how matching works, see [Routing](/http/routing).

### Running the Middleware

The matched request then passes through the middleware chain, from the outside in:

1. **Panic recovery**, which Copper installs automatically. If anything below panics, the error and stack are logged and the client receives a 500.
2. **Global middlewares**, in the order they are listed. In a generated project that means a request ID is placed in the context, `csql.TxMiddleware` opens a database transaction for mutating requests, and the request logger starts its timer.
3. **Route middlewares**, which run only for the route that declares them. Since they sit inside the global chain, they are the right place for concerns that apply to some endpoints but not others, such as auth on an admin route:

```go theme={null}
{
	Path:        "/admin/rockets",
	Methods:     []string{http.MethodPost},
	Middlewares: []chttp.Middleware{ro.authMW},
	Handler:     ro.HandleDecommissionRocket,
},
```

Each middleware wraps the next, so a request runs panic recovery, then each global middleware in order, then each route middleware in order, then your handler; the same chain unwinds in reverse as the response is written. To learn more, including the built-in middlewares and how to write your own, see [Middleware](/http/middleware).

### Handling the Request

Your handler is a plain `http.HandlerFunc` on a router struct. It reads path parameters with `chttp.URLParams`, decodes and validates the body, and calls into your [services](/the-basics/packages). Anything downstream that touches the database through `csql.Querier` automatically participates in the request's transaction, since the transaction travels in the request context. To learn more, see [Transactions](/database/transactions).

### Writing the Response

The handler writes its response through one of Copper's writers: `WriteJSON` for APIs, `WriteHTML` for Go templates, or the Inertia renderer for React pages. As the response is written, the middleware chain unwinds:

* `TxMiddleware` commits or rolls back the request's transaction based on the response status, and any `OnCommit` callbacks run once the commit succeeds. The full rules live in [Transactions](/database/transactions).
* The request logger records the method, path, status, and duration, and emits the built-in [HTTP metrics](/digging-deeper/metrics).

### Where Inertia Fits

An Inertia page render is an ordinary handler that ends in `inertia.Render` instead of `WriteJSON`, and the lifecycle above applies unchanged. The only difference is the response format, which the renderer picks per request:

* On a **first visit**, it renders the full HTML shell (`layouts/main.html`), embeds the page component name and props as JSON, and the [Vite render func](/frontend/vite) injects the right script tags. React boots and takes over.
* On **subsequent navigations**, Inertia's client sends the `X-Inertia` header, and the renderer responds with a small JSON payload of the next page's props instead of HTML. No full page load happens again.

Either way it is the same route, the same middleware chain, and the same transaction semantics. To learn more, see [Inertia](/frontend/inertia).

### Next

Now that you can trace a request end to end, you may want to read [App Lifecycle](/architecture/app-lifecycle) for what happens at startup and shutdown, or [Dependency Injection](/architecture/dependency-injection) for how the handler graph is assembled.
