# Module h2::client [−] [src]

Client implementation of the HTTP/2.0 protocol.

# Getting started

Running an HTTP/2.0 client requires the caller to establish the underlying connection as well as get the connection to a state that is ready to begin the HTTP/2.0 handshake. See here for more details.

This could be as basic as using Tokio’s `TcpStream` to connect to a remote host, but usually it means using either ALPN or HTTP/1.1 protocol upgrades.

Once a connection is obtained, it is passed to `handshake`, which will begin the HTTP/2.0 handshake. This returns a future that completes once the handshake process is performed and HTTP/2.0 streams may be initialized.

`handshake` uses default configuration values. There are a number of settings that can be changed by using `Builder` instead.

Once the handshake future completes, the caller is provided with a `Connection` instance and a `SendRequest` instance. The `Connection` instance is used to drive the connection (see Managing the connection). The `SendRequest` instance is used to initialize new streams (see Making requests).

# Making requests

Requests are made using the `SendRequest` handle provided by the handshake future. Once a request is submitted, an HTTP/2.0 stream is initialized and the request is sent to the server.

A request body and request trailers are sent using `SendRequest` and the server’s response is returned once the `ResponseFuture` future completes. Both the `SendStream` and `ResponseFuture` instances are returned by `SendRequest::send_request` and are tied to the HTTP/2.0 stream initialized by the sent request.

The `SendRequest::poll_ready` function returns `Ready` when a new HTTP/2.0 stream can be created, i.e. as long as the current number of active streams is below `MAX_CONCURRENT_STREAMS`. If a new stream cannot be created, the caller will be notified once an existing stream closes, freeing capacity for the caller. The caller should use `SendRequest::poll_ready` to check for capacity before sending a request to the server.

`SendRequest` enforces the `MAX_CONCURRENT_STREAMS` setting. The user must not send a request if `poll_ready` does not return `Ready`. Attempting to do so will result in an `Error` being returned.

# Managing the connection

The `Connection` instance is used to manage connection state. The caller is required to call `Connection::poll` in order to advance state. `SendRequest::send_request` and other functions have no effect unless `Connection::poll` is called.

The `Connection` instance should only be dropped once `Connection::poll` returns `Ready`. At this point, the underlying socket has been closed and no further work needs to be done.

The easiest way to ensure that the `Connection` instance gets polled is to submit the `Connection` instance to an executor. The executor will then manage polling the connection until the connection is complete. Alternatively, the caller can call `poll` manually.

# Example

    use h2::client;

    use http::{Request, Method};
    use std::error::Error;
    use tokio::net::TcpStream;

    #[tokio::main]
    pub async fn main() -> Result<(), Box<dyn Error>> {
        // Establish TCP connection to the server.
        let tcp = TcpStream::connect("127.0.0.1:5928").await?;
        let (h2, connection) = client::handshake(tcp).await?;
        tokio::spawn(async move {
            connection.await.unwrap();
        });

        let mut h2 = h2.ready().await?;
        // Prepare the HTTP request to send to the server.
        let request = Request::builder()
                        .method(Method::GET)
                        .uri("https://www.example.com/")
                        .body(())
                        .unwrap();

        // Send the request. The second tuple item allows the caller
        // to stream a request body.
        let (response, _) = h2.send_request(request, true).unwrap();

        let (head, mut body) = response.await?.into_parts();

        println!("Received response: {:?}", head);

        // The `flow_control` handle allows the caller to manage
        // flow control.
        //
        // Whenever data is received, the caller is responsible for
        // releasing capacity back to the server once it has freed
        // the data from memory.
        let mut flow_control = body.flow_control().clone();

        while let Some(chunk) = body.data().await {
            let chunk = chunk?;
            println!("RX: {:?}", chunk);

            // Let the server send more data.
            let _ = flow_control.release_capacity(chunk.len());
        }

        Ok(())
    }

## Structs

Builder | Builds client connections with custom configuration values.
Connection | Manages all state associated with an HTTP/2.0 client connection.
PushPromise | A pushed response and corresponding request headers
PushPromises | A stream of pushed responses and corresponding promised requests
PushedResponseFuture | A future of a pushed HTTP response.
ReadySendRequest | Returns a `SendRequest` instance once it is ready to send at least one request.
ResponseFuture | A future of an HTTP response.
SendRequest | Initializes new HTTP/2.0 streams on a connection by sending a request.

## Functions

handshake | Creates a new configured HTTP/2.0 client with default configuration values backed by `io`.