# `HttpDouble.Server`
[🔗](https://github.com/aszymanskiit/http_double/blob/main/lib/http_double/server.ex#L1)

OTP process that runs an HTTP server via Plug.Cowboy, holds static routes
and mock rules, and records HTTP call history.

Users normally interact with this module indirectly via the `HttpDouble`
facade, but the functions here are public to make supervision and advanced
control easier when needed.

# `mode`

```elixir
@type mode() :: :mock_first | :routes_only | :mock_only
```

Internal server mode.

# `t`

```elixir
@type t() :: %HttpDouble.Server{
  calls: [HttpDouble.call_record()],
  cowboy_ref: reference() | nil,
  host: String.t(),
  ip: :inet.ip_address(),
  max_calls: pos_integer(),
  mode: mode(),
  next_conn_id: non_neg_integer(),
  port: non_neg_integer() | nil,
  routes: [HttpDouble.Route.t()],
  rules: [HttpDouble.MockRule.t()]
}
```

Server state kept in the GenServer.

# `add_routes`

```elixir
@spec add_routes(GenServer.server(), [map()]) :: :ok
```

Adds one or more static routes at runtime.

# `add_rule`

```elixir
@spec add_rule(GenServer.server(), HttpDouble.MockRule.kind(), Keyword.t()) ::
  {:ok, reference()}
```

Registers a new stub or expectation rule.

This is the backing implementation for `HttpDouble.stub/2`, `stub/3`
and `HttpDouble.expect/3`.

# `calls`

```elixir
@spec calls(GenServer.server()) :: [HttpDouble.call_record()]
```

Returns the list of recorded calls, ordered from oldest to newest.

# `child_spec`

```elixir
@spec child_spec(Keyword.t()) :: Supervisor.child_spec()
```

Returns a child spec suitable for supervision trees.

# `delete_route`

```elixir
@spec delete_route(GenServer.server(), map()) :: :ok
```

Deletes a route identified by `:id` or by `{method, path}`.

# `endpoint`

```elixir
@spec endpoint(GenServer.server()) :: HttpDouble.endpoint()
```

Returns a convenient endpoint map `%{host, port, base_url}`.

# `host`

```elixir
@spec host(GenServer.server()) :: String.t()
```

Returns the logical host string reported by the server.

# `port`

```elixir
@spec port(GenServer.server()) :: non_neg_integer()
```

Returns the TCP port the server is listening on.

# `reset!`

```elixir
@spec reset!(GenServer.server()) :: :ok
```

Resets the server state (routes, rules, history).

# `serve_plug_conn`

```elixir
@spec serve_plug_conn(Plug.Conn.t(), GenServer.server()) :: Plug.Conn.t()
```

Handles a single request (Plug.Conn). Called from HttpDouble.Plug.

Reads the request body, converts to HttpDouble.Request, dispatches via the
server state, and returns a Plug.Conn response.

# `set_routes`

```elixir
@spec set_routes(GenServer.server(), [map()]) :: :ok
```

Replaces the full static route table.

# `start_link`

```elixir
@spec start_link(Keyword.t()) :: GenServer.on_start()
```

Starts a new server process.

Options:

  * `:port` – TCP port to listen on (0 = random free port, default)
  * `:ip` – IP tuple to bind to (defaults to `{127, 0, 0, 1}`)
  * `:host` – logical host string reported by `HttpDouble.host/1` (defaults to `"127.0.0.1"`)
  * `:routes` – list of static route definitions
  * `:mode` – `:mock_first` (default), `:routes_only`, or `:mock_only`
  * `:name` – optional registered name (e.g. via `Registry`)

# `update_route`

```elixir
@spec update_route(GenServer.server(), map()) :: :ok
```

Updates a single route identified by `:id` or by `{method, path}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
