# Embedding in an HTTP Server

The `webtransport:accept/4` function lets you add WebTransport to any
HTTP/3 or HTTP/2 server. Instead of `start_listener/2` (which creates its
own server), you call `accept/4` from your existing request handler --
the same pattern as upgrading a request to WebSocket.

## HTTP/3 (quic_h3)

### 1. Merge WT settings into your server opts

```erlang
H3Opts = maps:merge(webtransport:h3_settings(), #{
    cert => CertDer,
    key => PrivateKey,
    handler => fun my_handler/5
}),
{ok, _} = quic_h3:start_server(my_server, 443, H3Opts).
```

`h3_settings/0` returns:

| Key | Value |
|-----|-------|
| `settings` | H3 SETTINGS (wt_enabled, flow-control windows, draft-02 compat) |
| `stream_type_handler` | Claims WT extension streams (0x41 bidi, 0x54 uni) |
| `h3_datagram_enabled` | `true` |
| `quic_opts` | `#{max_datagram_frame_size => 65535, reset_stream_at => true}` |
| `connection_handler` | Creates a per-connection WT stream router |

Pass options to customize:

```erlang
webtransport:h3_settings(#{
    compat_mode => latest,          %% default: auto
    max_data => 4194304,            %% default: 1 MB
    max_streams_bidi => 200         %% default: 100
}).
```

### 2. Route requests and accept WebTransport

```erlang
my_handler(H3Conn, StreamId, <<"CONNECT">>, <<"/chat">>, Headers) ->
    {ok, _Session} = webtransport:accept(H3Conn, StreamId, Headers, #{
        transport => h3,
        handler => chat_handler,
        handler_opts => #{room => lobby}
    });

my_handler(H3Conn, StreamId, <<"CONNECT">>, <<"/game">>, Headers) ->
    {ok, _Session} = webtransport:accept(H3Conn, StreamId, Headers, #{
        transport => h3,
        handler => game_handler
    });

my_handler(H3Conn, StreamId, <<"GET">>, <<"/health">>, _Headers) ->
    quic_h3:send_response(H3Conn, StreamId, 200, []),
    quic_h3:send_data(H3Conn, StreamId, <<"ok">>, true);

my_handler(H3Conn, StreamId, _Method, _Path, _Headers) ->
    quic_h3:send_response(H3Conn, StreamId, 404, []),
    quic_h3:send_data(H3Conn, StreamId, <<"not found">>, true).
```

## HTTP/2 (erlang_h2)

### 1. Merge WT settings into your server opts

```erlang
H2Opts = maps:merge(webtransport:h2_settings(), #{
    cert => "cert.pem",
    key => "key.pem",
    handler => fun my_h2_handler/5
}),
{ok, _} = h2:start_server(443, H2Opts).
```

`h2_settings/0` returns:

| Key | Value |
|-----|-------|
| `enable_connect_protocol` | `true` |
| `settings` | H2 SETTINGS (enable_connect_protocol, wt_initial_max_*) |

### 2. Route requests

```erlang
my_h2_handler(Conn, StreamId, <<"CONNECT">>, <<"/wt">>, Headers) ->
    {ok, _Session} = webtransport:accept(Conn, StreamId, Headers, #{
        transport => h2,
        handler => my_wt_handler
    });

my_h2_handler(Conn, StreamId, <<"GET">>, Path, Headers) ->
    serve_static(Conn, StreamId, Path, Headers).
```

## What `accept/4` does

`accept(Conn, StreamId, Headers, Opts)` performs these steps:

1. Runs `origin_check/2` on the handler (if exported)
2. Validates the CONNECT request (`:protocol`, compat mode detection for h3)
3. Starts a `webtransport_session` gen_statem
4. Registers it as the stream handler via `quic_h3:set_stream_handler/3`
   (h3) or `h2:set_stream_handler/3` (h2) -- same API the transport uses
   for raw streams
5. For h3: registers with the per-connection router so extension streams
   (bidirectional 0x41, unidirectional 0x54) are routed to the session
6. Sends 200 OK to the client
7. Returns `{ok, Session}` or `{error, Reason}`

### Options

| Key | Default | Description |
|-----|---------|-------------|
| `transport` | `h3` | `h3` or `h2` |
| `handler` | required | Module implementing `webtransport_handler` |
| `handler_opts` | `#{}` | Passed to `handler:init/3` |
| `compat_mode` | `auto` | h3 draft selection |
| `max_data` | 1048576 | Session flow-control window |
| `max_streams_bidi` | 100 | Max bidi streams |
| `max_streams_uni` | 100 | Max uni streams |

## Relationship to `start_listener/2`

`start_listener/2` is a convenience wrapper that:

1. Creates a quic_h3 or h2 server
2. Installs a catch-all handler that calls `accept/4` for every CONNECT
3. Returns 405 for non-CONNECT methods

Use `start_listener/2` for simple WT-only servers. Use `h3_settings/0` +
`accept/4` when you need to:

- Serve regular HTTP alongside WebTransport on the same port
- Route different paths to different handlers
- Integrate with an existing HTTP server framework
