---
name: "Protocol::HTTP2::Client"
section: "3pm"
platform: "linux"
package: "libprotocol-http2-perl"
version: "1.11-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Protocol::HTTP2::Client"
---

# Protocol::HTTP2::Client(3pm)

HTTP/2 client

## NAME

Protocol::HTTP2::Client - HTTP/2 client

## SYNOPSIS

```
    use Protocol::HTTP2::Client;
    # Create client object
    my $client = Protocol::HTTP2::Client->new;
    # Prepare first request
    $client->request(
        # HTTP/2 headers
        ':scheme'    => 'http',
        ':authority' => 'localhost:8000',
        ':path'      => '/',
        ':method'    => 'GET',
        # HTTP/1.1 headers
        headers      => [
            'accept'     => '*/*',
            'user-agent' => 'perl-Protocol-HTTP2/0.13',
        ],
        # Callback when receive server's response
        on_done => sub {
            my ( $headers, $data ) = @_;
            ...
        },
    );
    # Protocol::HTTP2 is just HTTP/2 protocol decoder/encoder
    # so you must create connection yourself
    use AnyEvent;
    use AnyEvent::Socket;
    use AnyEvent::Handle;
    my $w = AnyEvent->condvar;
    # Plain-text HTTP/2 connection
    tcp_connect 'localhost', 8000, sub {
        my ($fh) = @_ or die "connection failed: $!\n";

        my $handle;
        $handle = AnyEvent::Handle->new(
            fh       => $fh,
            autocork => 1,
            on_error => sub {
                $_[0]->destroy;
                print "connection error\n";
                $w->send;
            },
            on_eof => sub {
                $handle->destroy;
                $w->send;
            }
        );
        # First write preface to peer
        while ( my $frame = $client->next_frame ) {
            $handle->push_write($frame);
        }
        # Receive servers frames
        # Reply to server
        $handle->on_read(
            sub {
                my $handle = shift;
                $client->feed( $handle->{rbuf} );
                $handle->{rbuf} = undef;
                while ( my $frame = $client->next_frame ) {
                    $handle->push_write($frame);
                }
                # Terminate connection if all done
                $handle->push_shutdown if $client->shutdown;
            }
        );
    };
    $w->recv;
```

## DESCRIPTION

Protocol::HTTP2::Client is HTTP/2 client library. It's intended to make http2-client implementations on top of your favorite event-loop.

### METHODS

*new*

Initialize new client object

```
    my $client = Protocol::HTTP2::Client->new( %options );
```

Available options:

- on\_push =\> sub {...}

  If server send push promise this callback will be invoked

  ```
      on_push => sub {
          # received PUSH PROMISE headers
          my $pp_header = shift;
          ...

          # if we want reject this push
          # return undef

          # if we want to accept pushed resource
          # return callback to receive data
          return sub {
              my ( $headers, $data ) = @_;
              ...
          }
      },
  ```

- upgrade =\> 0\|1

  Use HTTP/1.1 Upgrade to upgrade protocol from HTTP/1.1 to HTTP/2. Upgrade possible only on plain (non-tls) connection. Default value is 0.

  See Starting HTTP/2 for "http" URIs \<https://tools.ietf.org/html/rfc7540#section-3.2\>

- keepalive =\> 0\|1

  Keep connection alive after requests. Default value is 0. Don't forget to explicitly call close method if set this to true.

- on\_error =\> sub {...}

  Callback invoked on protocol errors

  ```
      on_error => sub {
          my $error = shift;
          ...
      },
  ```

- on\_change\_state =\> sub {...}

  Callback invoked every time when http/2 streams change their state. See Stream States \<https://tools.ietf.org/html/rfc7540#section-5.1\>

  ```
      on_change_state => sub {
          my ( $stream_id, $previous_state, $current_state ) = @_;
          ...
      },
  ```

*request*

Prepare HTTP/2 request.

```
    $client->request(
        # HTTP/2 headers
        ':scheme'    => 'http',
        ':authority' => 'localhost:8000',
        ':path'      => '/items',
        ':method'    => 'POST',
        # HTTP/1.1 headers
        headers      => [
            'content-type' => 'application/x-www-form-urlencoded',
            'user-agent' => 'perl-Protocol-HTTP2/0.06',
        ],
        # Callback when receive server's response
        on_done => sub {
            my ( $headers, $data ) = @_;
            ...
        },
        # Callback when receive stream reset
        on_error => sub {
            my $error_code = shift;
        },
        # Body of POST request
        data => "hello=world&test=done",
    );
```

You can chaining request one by one:

```
    $client->request( 1-st request )->request( 2-nd request );
```

Available callbacks:

- on\_done =\> sub {...}

  Invoked when full servers response is available

  ```
      on_done => sub {
          my ( $headers, $data ) = @_;
          ...
      },
  ```

- on\_headers =\> sub {...}

  Invoked as soon as headers have been successfully received from the server

  ```
      on_headers => sub {
          my $headers = shift;
          ...
          # if we want reject any data
          # return undef
          # continue
          return 1
      }
  ```

- on\_data =\> sub {...}

  If specified all data will be passed to this callback instead if on\_done. on\_done will receive empty string.

  ```
      on_data => sub {
          my ( $partial_data, $headers ) = @_;
          ...
          # if we want cancel download
          # return undef
          # continue downloading
          return 1
      }
  ```

- on\_error =\> sub {...}

  Callback invoked on stream errors

  ```
      on_error => sub {
          my $error = shift;
          ...
      }
  ```

*keepalive*

Keep connection alive after requests

```
    my $bool = $client->keepalive;
    $client = $client->keepalive($bool);
```

*shutdown*

Get connection status:

- 0 - active

  - 1 - closed (you can terminate connection)

  *close*

Explicitly close connection (send GOAWAY frame). This is required if client has keepalive option enabled.

*next\_frame*

get next frame to send over connection to server. Returns:

- undef - on error

  - 0 - nothing to send

  - binary string - encoded frame

  ```
    # Example
    while ( my $frame = $client->next_frame ) {
        syswrite $fh, $frame;
    }
```

*feed*

Feed decoder with chunks of server's response

```
    sysread $fh, $binary_data, 4096;
    $client->feed($binary_data);
```

*ping*

Send ping frame to server (to keep connection alive)

```
    $client->ping
```

or

```
    $client->ping($payload);
```

Payload can be arbitrary binary string and must contain 8 octets. If payload argument is omitted client will send random data.
