# Server context and middleware

> Create request-scoped context and apply middleware globally or to selected routes.

Use server context for values shared by middleware and handlers during one request. Use middleware when a policy must run around handlers or stop a request with a contract-declared error. This page uses the shared `contract` from [contract authoring](https://hulla.dev/docs/api/core/contracts.md); the authentication example additionally assumes that the contract declares an `UNAUTHENTICATED` error.

## Create portable request context

`defineServer()` context receives a portable `signal` and matched `route` metadata. Return the application values needed during the request; the factory's resolved return type becomes `input.context`.

```ts
import { defineServer } from '@hulla/api/server'
import { contract } from './contract'

const server = defineServer(contract, {
  context: ({ route, signal }) => ({
    requestId: crypto.randomUUID(),
    routeKey: route.key.join('.'),
    signal,
  }),
})
```

This context does not depend on Fetch or another host, so its implementations can be mounted through compatible adapters or called in process. Pass `signal` to cancellable work so downstream operations can stop when the request is cancelled.

## Add native context only for host-specific needs

When application logic needs a native request value, create the adapter first and wrap the context factory with `adapter.context()`. This example reads an identity header; middleware and handlers receive the resulting `userId`, not the native `Request`.

```ts
import { defineServer } from '@hulla/api/server'
import { fetchAdapter } from '@hulla/api/fetch'
import { contract } from './contract'

const adapter = fetchAdapter()
const server = defineServer(contract, {
  context: adapter.context(({ request }) => ({
    userId: request.headers.get('x-user-id') ?? undefined,
  })),
})
```

> Wrapping a context factory with `adapter.context()` binds every implementation from that server definition to the same adapter kind. Keep context portable unless handlers genuinely need native host data.

The adapter still owns request parsing and response writing. See [server adapters](https://hulla.dev/docs/api/servers.md) for host-specific setup and [adapter behavior](https://hulla.dev/docs/api/reference/adapter-conformance.md) for the behavior every adapter must preserve.

## Apply middleware globally or to a route scope

Use `server.middleware()` to type middleware against the context and contract. Middleware receives `signal`, `context`, `route`, `next`, and declared `errors` when the contract defines them.

```ts
const logRequest = server.middleware(async ({ context, route, next }) => {
  console.info(context.userId, route.method, route.path)
  return next()
})

const requireUser = server.middleware(async ({ context, errors, next }) => {
  if (!context.userId) return errors.UNAUTHENTICATED()
  return next()
})
```

Both functions use the Fetch-backed `server` above, so `context.userId` is inferred. `UNAUTHENTICATED` must be declared in the contract, as assumed at the start of this page. Returning the declared error skips the remaining middleware and handler. Middleware and handlers may also throw a declared error. See [error handling](https://hulla.dev/docs/api/core/errors.md).

Apply middleware while building the implementation:

```ts
const implementation = server
  .use(logRequest)
  .use(contract.routes.users, requireUser)
  .implement({
    health: ({ response }) => response(200, 'ok'),
    users: {
      byId: ({ params, response }) =>
        params.id === 'ada'
          ? response(200, { id: 'ada', name: 'Ada' })
          : response(404, { message: 'User not found' }),
      rename: ({ params, body, response }) =>
        response(200, { id: params.id, name: body.name }),
    },
  })
```

| Registration               | Routes that run it            |
| -------------------------- | ----------------------------- |
| `.use(middleware)`         | Every route                   |
| `.use(router, middleware)` | Every route below that router |
| `.use(route, middleware)`  | That route only               |

Calls to `use()` preserve declaration order. For a matched route, middleware wraps the next middleware and finally the handler: code before `await next()` runs on entry, and code after it resumes as the result returns outward. Separate registrations in overlapping scopes each run.

`next()` is single-use. Call it once to continue, or return a response or declared error to stop. Implementations created from child scopes retain middleware from those scopes; [server fragments and composition](https://hulla.dev/docs/api/core/server-composition.md) shows how that inheritance behaves when fragments are mounted or composed.
