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

# Client

`moqt.Dialer` manages client-side operations for the MoQ protocol. It establishes sessions with MoQ servers over WebTransport, native QUIC, and QMux over WebSocket.

<Accordion title="Overview">
  ```go theme={null}
  func main() {
      // Create a new dialer
  	dialer := moqt.Dialer{
  		TLSConfig: &tls.Config{
  			InsecureSkipVerify: true,
  		},
  	}

  	// Dial and establish a session with the server
  	sess, err := dialer.Dial(context.Background(), "https://[addr]:[port]/[path]", nil)
  	if err != nil {
  		log.Fatalf("Failed to dial: %v", err)
  	}
  	defer sess.CloseWithError(moqt.NoError, "done")

  	// Use the session (e.g., subscribe to tracks, receive announcements)
  }
  ```
</Accordion>

## Initialize a Dialer

There is no dedicated function (such as a constructor) for initializing a dialer.
Users define the struct directly and assign values to its fields as needed.

```go theme={null}
    dialer := moqt.Dialer{
		// Set dialer options here
	}
```

### Configuration

The following table describes the public fields of the `moqt.Dialer` struct:

| Field | Type | Description |
| - | - | - |
| `TLSConfig` | [`*tls.Config`](https://pkg.go.dev/crypto/tls#Config) | TLS configuration for secure connections |
| `QUICConfig` | [`*quic.Config`](https://pkg.go.dev/github.com/quic-go/quic-go#Config) | QUIC configuration for raw QUIC connections and for the connection under a WebTransport session (datagrams and stream reset with partial delivery are turned on there). A WebSocket session takes the settings QMux shares with QUIC. A zero `KeepAlivePeriod` sends no keep-alives on any transport; a negative one is refused. |
| `Config` | [`*moqt.Config`](https://pkg.go.dev/github.com/qumo-dev/gomoqt/moqt#Config) | MoQ protocol configuration |
| `DialQUICFunc` | `func(ctx, addr, tlsConfig, quicConfig) (StreamConn, error)` | Custom QUIC dial function. If nil, the default dialer is used. |
| `DialWebTransportFunc` | `func(ctx, addr, header, tlsConfig, quicConfig) (*http.Response, WebTransportSession, error)` | Custom WebTransport dial function. If nil, the default dialer is used. `quicConfig` is `QUICConfig` as it is. |
| `FetchHandler` | [`moqt.FetchHandler`](https://pkg.go.dev/github.com/qumo-dev/gomoqt/moqt#FetchHandler) | Handles incoming fetch requests on WebTransport sessions. If nil, fetch requests are not handled. |
| `OnGoaway` | `func(newSessionURI string)` | Called when the server requests session migration. The `newSessionURI` parameter contains the redirect URI, which may be empty. |
| `Logger` | [`*slog.Logger`](https://pkg.go.dev/log/slog#Logger) | Logger for connection and session events. If nil, logging is disabled. |

<Tabs>
  <Tab title="Using Default QUIC">
    [`quic-go/quic-go`](https://github.com/quic-go/quic-go) is used internally as the default QUIC implementation when relevant fields which is set for customization are not set or `nil`.

    [`quic-go/quic-go`](https://github.com/quic-go/quic-go)
  </Tab>

  <Tab title="Using Custom QUIC">
    To use a custom QUIC implementation, you need to provide your own dial function. When `Dialer.DialQUICFunc` is set, it is used to dial QUIC connections instead of the default implementation.

    ```go {filename="gomoqt/moqt/dialer.go",base_url="https://github.com/qumo-dev/gomoqt/tree/main/moqt/dialer.go"} theme={null}
    type Dialer struct {
        // ...
    	DialQUICFunc func(ctx context.Context, addr string, tlsConfig *tls.Config, quicConfig *quic.Config) (StreamConn, error)
        // ...
    }
    ```
  </Tab>
</Tabs>

<Tabs>
  <Tab title="Using Default WebTransport">
    [`okdaichi/webtransport-go`](https://github.com/okdaichi/webtransport-go) — a fork of `quic-go/webtransport-go` carrying a custom upgrader — is used internally as the default WebTransport implementation when the relevant customization fields are not set or are `nil`.

    [`okdaichi/webtransport-go`](https://github.com/okdaichi/webtransport-go)
  </Tab>

  <Tab title="Using Custom WebTransport">
    To use a custom WebTransport implementation, you need to provide your own dial function. When `Dialer.DialWebTransportFunc` is set, it is used to dial WebTransport connections instead of the default implementation.

    ```go {filename="gomoqt/moqt/dialer.go",base_url="https://github.com/qumo-dev/gomoqt/tree/main/moqt/dialer.go"} theme={null}
    type Dialer struct {
        // ...
    	DialWebTransportFunc func(ctx context.Context, addr string, header http.Header, tlsConfig *tls.Config, quicConfig *quic.Config) (*http.Response, WebTransportSession, error)
        // ...
    }
    ```
  </Tab>
</Tabs>

## Dial and Establish Session

`Dial` is the only way to establish a session. It selects the transport from the URL scheme:

* `https://` — WebTransport (HTTP/3)
* `moqt://` — Native QUIC
* `wss://` — QMux over WebSocket, the binding for clients that cannot use WebTransport (`ws://` does without TLS)

Over WebSocket everything shares one TCP connection: a lost segment delays every stream, and there are no unreliable datagrams. Prefer the other two where they work. `Dialer.QUICConfig` configures a WebSocket session too, with the settings QMux shares with QUIC (stream limits, receive windows, keep-alive, idle and handshake timeouts, datagrams), and `Dialer.DialWebSocketFunc` replaces the dial. Like the other two dial functions it receives `QUICConfig` as it is: what the default dials do with it (turning on what WebTransport needs, and refusing a negative keep-alive) is left to the function.

```go theme={null}
	var mux *moqt.TrackMux
	sess, err := dialer.Dial(ctx, "https://[addr]:[port]/[path]", mux)
	if err != nil {
		// Handle error
		return
	}

	// Handle session
```

The URL's path selects the server-side endpoint and is reported by
[`Session.RequestURI`](/moq/session#request-uri). A URL with no path is dialed as `/`.
On native QUIC the path travels as the SETUP Path parameter, since that binding
has no request URI of its own.

<Note>
  **Note: Queries**

  A query reaches the server on both bindings, and
  [`Session.RequestURI`](/moq/session#request-uri) carries it after `?` on both
  sides. On `https://` it is part of the HTTP request URI; on `moqt://` it is
  appended to the SETUP Path parameter after `?`, as draft-ietf-moq-transport and
  the moq-lite reference implementation do. That is how a credential such as `?jwt=` reaches a server over native QUIC.
  A fragment is client-side only and is never sent on either binding.
</Note>

To supply your own connection or handshake, set `DialQUICFunc` or
`DialWebTransportFunc` on the `Dialer` — see the **Using Custom QUIC** tab under
[Initialize a Dialer](#initialize-a-dialer). These replace the handshake `Dial`
performs; `Dial` still parses the URL and selects the transport from it, so they
are not a way to bypass URL handling.

<Note>
  **Note: Nil TrackMux**

  When `mux` is set to `nil`, the `moqt.DefaultMux` will be used by default.
  Ensure that the `mux` is properly configured for your use case to avoid unexpected behavior.
</Note>

<Note>
  **Note: ALPN Negotiation**

  For native QUIC connections, the dialer automatically sets the ALPN token to `moq-lite-05` (`moqt.NextProtoMOQ`) if `TLSConfig.NextProtos` is not configured.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.