---
title: Middleware
sidebar:
  icon: layers
description: Run code around a procedure - add a user, skip the handler, or change the result.
---

`.use(mw)` wraps a procedure. `return next({ ctx })` continues and merges context. Skip `next()` to skip the handler. `await next()` to wrap the result.

```ts twoslash
import { RpcError, tacho } from "tacho";

const rpc = tacho<{ req: Request; user?: string }>();

const protect = rpc.use(async ({ ctx, next }) => {
  const user = ctx.req.headers.get("x-user");
  if (!user) {
    throw new RpcError({ code: -32001, message: "unauthorized" });
  }
  return next({ ctx: { user } });
});

export const router = rpc({
  me: protect.run(({ ctx }) => ctx.user),
  greet: protect
    .use(async ({ next }) => `hi ${await next()}`)
    .run(({ ctx }) => ctx.user),
  cached: protect.use(async () => "from-cache").run(() => "handler"),
});
```
