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

# meow:http

> A Web-standard HTTP/1.1 server — serve a Request → Response handler.

`meow:http` exposes a single function, `serve()`, that starts a Web-standard
HTTP/1.1 server. Your handler receives a standard `Request` and returns a standard
`Response` (or a promise of one) — the same objects you use with `fetch`.

```typescript theme={null}
import { serve } from "meow:http";

serve((req: Request) => {
  return new Response("Hello from meow!\n");
}, { port: 3000 });
```

## `serve()`

Accepts either a handler-first or an options-only (Deno-style) form:

```typescript theme={null}
serve(handler, { port: 3000 });          // classic
serve({ port: 3000, fetch: handler });    // Deno-style
```

```typescript theme={null}
function serve(
  handlerOrOptions: Handler | ServeOptions,
  maybeOptions?: ServeOptions,
): Server;

type Handler = (request: Request) => Response | Promise<Response>;
```

The listener binds **synchronously**, so `server.addr` carries the resolved address
the moment `serve()` returns.

## `ServeOptions`

<ParamField path="port" type="number" default="8000">
  TCP port to bind. Pass `0` to let the OS assign a free port (read it back from
  `server.addr.port`).
</ParamField>

<ParamField path="hostname" type="string" default="&#x22;0.0.0.0&#x22;">
  Interface to bind.
</ParamField>

<ParamField path="signal" type="AbortSignal">
  Abort to stop accepting connections and drain in-flight requests.
</ParamField>

<ParamField path="onListen" type="(addr: NetAddr) => void">
  Called once the listener is bound, with the resolved `{ hostname, port }`.
</ParamField>

<ParamField path="fetch" type="Handler">
  The per-request handler, when using the options-only form.
</ParamField>

## `Server`

```typescript theme={null}
interface Server {
  readonly addr: NetAddr;          // { hostname, port } — resolved
  shutdown(): Promise<void>;       // stop accepting, drain, release. Idempotent.
  readonly finished: Promise<void>; // resolves when the accept loop fully stops
}

interface NetAddr {
  readonly hostname: string;
  readonly port: number;
}
```

## Examples

<CodeGroup>
  ```typescript Routing with URLPattern theme={null}
  import { serve } from "meow:http";

  const user = new URLPattern({ pathname: "/users/:id" });

  serve((req) => {
    const match = user.exec(req.url);
    if (match) {
      return Response.json({ id: match.pathname.groups.id });
    }
    return new Response("Not found", { status: 404 });
  }, { port: 3000 });
  ```

  ```typescript Reading the resolved port theme={null}
  import { serve } from "meow:http";

  const server = serve(() => new Response("ok"), {
    port: 0,                          // OS-assigned
    onListen: ({ hostname, port }) => {
      console.log(`listening on http://${hostname}:${port}`);
    },
  });

  console.log(server.addr.port);      // the actual port
  ```

  ```typescript Graceful shutdown theme={null}
  import { serve } from "meow:http";

  const controller = new AbortController();
  const server = serve(() => new Response("ok"), {
    port: 3000,
    signal: controller.signal,
  });

  // later…
  controller.abort();      // or: await server.shutdown();
  await server.finished;   // resolves once draining completes
  ```

  ```typescript JSON echo theme={null}
  import { serve } from "meow:http";

  serve(async (req) => {
    if (req.method !== "POST") {
      return new Response("Method Not Allowed", { status: 405 });
    }
    const body = await req.json();
    return Response.json({ youSent: body });
  }, { port: 3000 });
  ```
</CodeGroup>

## Error handling

* A handler that throws, or returns something other than a `Response`, yields a
  `500` and logs the failure — one bad request never takes down the server.
* If the listener can't bind — for example, the port is already in use — the error
  surfaces through `server.finished` (it rejects) rather than throwing out of
  `serve()`.

<Card title="meow:ui" icon="palette" href="/api/ui">
  On-brand status output for your programs and scripts.
</Card>
