# `ZenWebsocket.MessageHandler`
[🔗](https://github.com/ZenHive/zen_websocket/blob/v0.9.0/lib/zen_websocket/message_handler.ex#L1)

Message handling utilities for WebSocket connections.

- Parse incoming WebSocket frames and Gun messages
- Route messages to user-provided handler functions
- Handle control frames (ping/pong) automatically
- Process WebSocket upgrade responses

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `create_handler` | 1 | Create a callback function for handling specific message types. | `opts: value` |
| `default_handler` | 1 | Default message handler that accepts and discards messages. | `message: value` |
| `handle_control_frame` | 3 | Handle WebSocket control frames automatically. | `decoded_frame: exchange_data`, `conn_pid: value`, `stream_ref: value` |
| `decode_and_handle_control` | 1 | Decode a WebSocket frame and handle control frames automatically. | `frame_tuple: exchange_data` |
| `handle_message` | 2 | Handle incoming Gun messages and WebSocket frames. | `message: exchange_data`, `handler_fun: value` |

# `create_handler`

```elixir
@spec create_handler(keyword()) :: (term() -&gt; any())
```

Create a callback function for handling specific message types.

# `decode_and_handle_control`

```elixir
@spec decode_and_handle_control(tuple()) ::
  {:ok, {:data, {atom(), binary()}}}
  | {:ok, :control_frame_handled}
  | {:error, {:protocol_error, term()}}
```

Decode a WebSocket frame and handle control frames automatically.
Returns decoded data frames without invoking any handler callback.

Used by the Client GenServer which has its own routing layer (route_data_frame)
for JSON parsing, subscription routing, and heartbeat handling.

# `default_handler`

```elixir
@spec default_handler(term()) :: :ok
```

Default message handler that accepts a message and discards it, returning `:ok`.

This is the fallback handler everywhere a handler is not supplied — except
`ZenWebsocket.Client.connect/2`, which installs a parent-forwarding handler via
`ZenWebsocket.Client.CallFacade.with_default_handler/2`. Any other path that falls
back to this function silently drops every inbound message, so supply your own
handler when you need to observe traffic.

# `handle_control_frame`

```elixir
@spec handle_control_frame(term(), pid(), reference()) :: :handled | :not_control
```

Handle WebSocket control frames automatically.
Returns :handled for control frames, :not_control for data frames.

# `handle_message`

```elixir
@spec handle_message(tuple(), (term() -&gt; any())) ::
  {:ok, term()} | {:error, {:protocol_error, term()}}
```

Handle incoming Gun messages and WebSocket frames.
Routes messages to appropriate handler function.

---

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