# `ReverseIt.Config`
[🔗](https://github.com/chrismccord/reverse_it/blob/main/lib/reverse_it/config.ex#L1)

Configuration parser and validator for reverse proxy settings.

# `t`

```elixir
@type t() :: %ReverseIt.Config{
  add_headers: [{String.t(), String.t()}],
  connect_ip: :inet.ip_address() | nil,
  connect_timeout: non_neg_integer(),
  error_response: {non_neg_integer(), String.t()},
  forwarded_headers: :append | :replace | false,
  host: String.t(),
  max_request_body_size: non_neg_integer() | :infinity,
  max_request_header_bytes: pos_integer(),
  max_request_header_line_bytes: pos_integer(),
  max_request_headers: pos_integer(),
  max_request_target_bytes: pos_integer(),
  max_response_body_size: non_neg_integer() | :infinity,
  max_response_header_bytes: pos_integer(),
  max_websocket_frame_size: pos_integer(),
  max_websocket_pending_bytes: non_neg_integer(),
  max_websocket_pending_frames: non_neg_integer(),
  max_websocket_upgrade_response_body_size: non_neg_integer(),
  name: atom(),
  path_prefix: String.t() | nil,
  pool_timeout: non_neg_integer(),
  port: non_neg_integer(),
  preserve_host_header: boolean(),
  protocols: [:http1 | :http2],
  remove_headers: MapSet.t(String.t()),
  request_body_buffer_size: pos_integer(),
  request_body_chunk_size: pos_integer(),
  request_body_read_timeout: non_neg_integer(),
  response_header_retries: non_neg_integer(),
  response_header_timeout: non_neg_integer(),
  scheme: :http | :https | :ws | :wss,
  strip_path: String.t() | nil,
  unix_socket: String.t() | nil,
  upstream_connection: :pooled | :one_shot,
  upstream_idle_timeout: non_neg_integer(),
  upstream_send_timeout: non_neg_integer(),
  verify_tls: boolean(),
  websocket_backend_upgrade_timeout: non_neg_integer(),
  websocket_compress: boolean(),
  websocket_fullsweep_after: non_neg_integer() | nil,
  websocket_idle_timeout: non_neg_integer(),
  websocket_max_heap_size: :erlang.max_heap_size() | nil,
  websocket_validate_utf8: boolean()
}
```

# `build_target_path`

```elixir
@spec build_target_path(t(), String.t()) :: String.t()
```

Builds the target path for the backend request.

# `http_scheme`

```elixir
@spec http_scheme(t()) :: :http | :https
```

Converts WebSocket scheme to HTTP scheme for Mint connection.

# `parse`

```elixir
@spec parse(keyword()) :: {:ok, t()} | {:error, String.t()}
```

Parses proxy configuration from options.

## Options

  * `:name` - Name of the Finch pool to use (required)
  * `:backend` - Backend URL (required). Can be http://, https://, ws://, or wss://
  * `:connect_ip` - Vetted IPv4/IPv6 tuple to dial while retaining the backend hostname for TLS and HTTP; requires `:one_shot` and cannot be combined with `:unix_socket`
  * `:unix_socket` - Connect to this Unix-domain socket instead of the backend host/port
  * `:upstream_connection` - `:pooled` or `:one_shot` (default: `:pooled`)
  * `:strip_path` - Path prefix to strip from incoming requests before proxying
  * `:connect_timeout` - Connection timeout in milliseconds (default: 5_000)
  * `:pool_timeout` - Finch pool checkout timeout in milliseconds (default: 5_000)
  * `:response_header_timeout` - Time to wait for backend response headers (default: 30_000)
  * `:response_header_retries` - Retries for replay-safe requests that fail before response headers (default: 0)
  * `:upstream_idle_timeout` - Rolling idle timeout for backend data (default: 55_000)
  * `:upstream_send_timeout` - Socket write timeout for direct HTTP/WebSocket connections (default: 55_000); configure on the supervisor child for pooled HTTP
  * `:request_body_read_timeout` - Rolling timeout while reading client request bodies (default: 55_000)
  * `:protocols` - List of supported upstream HTTP protocols (default: [:http1])
  * `:verify_tls` - Verify TLS certificates (default: true)
  * `:add_headers` - List of headers to add to backend requests (default: [])
  * `:remove_headers` - List of header names to remove from client requests (default: [])
  * `:forwarded_headers` - `:append`, `:replace`, or `false` for X-Forwarded-* behavior (default: :append)
  * `:preserve_host_header` - Preserve the original Host header instead of the backend host (default: false)
  * `:max_request_body_size` - Maximum request body size in bytes (default: 100MB, :infinity for unlimited)
  * `:request_body_buffer_size` - Body size buffered before switching to request streaming (default: 1MB)
  * `:max_response_body_size` - Maximum response body size in bytes (default: :infinity)
  * `:max_response_header_bytes` - Maximum backend response header bytes (default: 64KB)
  * `:max_request_target_bytes` - Maximum request path/query bytes (default: 8KB)
  * `:max_request_header_line_bytes` - Maximum single request header bytes (default: 8KB)
  * `:max_request_header_bytes` - Maximum total request header bytes (default: 64KB)
  * `:max_request_headers` - Maximum number of request headers (default: 100)
  * `:websocket_idle_timeout` - WebSocket client idle timeout (default: 55_000)
  * `:websocket_backend_upgrade_timeout` - Backend WebSocket upgrade timeout (default: 5_000)
  * `:max_websocket_upgrade_response_body_size` - Buffered upgrade rejection body limit (default: 64KB); a smaller `:max_response_body_size` also applies
  * `:max_websocket_frame_size` - Maximum client/backend WebSocket message size (default: 16MB)
  * `:max_websocket_pending_bytes` - Maximum frames buffered before backend upgrade (default: 1MB)
  * `:max_websocket_pending_frames` - Maximum frame count buffered before backend upgrade (default: 16)
  * `:websocket_compress` - Negotiate client WebSocket compression (default: false)
  * `:error_response` - Response to return when backend fails (default: {502, "Bad Gateway"})

## Examples

    iex> ReverseIt.Config.parse(backend: "http://localhost:4000")
    {:ok, %ReverseIt.Config{scheme: :http, host: "localhost", port: 4000, ...}}

    iex> ReverseIt.Config.parse(backend: "https://api.example.com/v1", strip_path: "/api", verify_tls: false)
    {:ok, %ReverseIt.Config{...}}

# `transport_opts`

```elixir
@spec transport_opts(t()) :: keyword()
```

Returns transport options for direct Mint connections.

# `websocket?`

```elixir
@spec websocket?(t()) :: boolean()
```

Returns true if the scheme is for WebSocket connections.

# `websocket_scheme`

```elixir
@spec websocket_scheme(t()) :: :ws | :wss
```

Returns the WebSocket scheme to use for a backend upgrade.

---

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