Protocol::HTTP2::Server(3pm)

NAME
Protocol::HTTP2::Server - HTTP/2 server

SYNOPSIS
    use Protocol::HTTP2::Server;

    # You must create tcp server yourself
    use AnyEvent;
    use AnyEvent::Socket;
    use AnyEvent::Handle;

    my $w = AnyEvent->condvar;

    # Plain-text HTTP/2 connection
    tcp_server 'localhost', 8000, sub {
        my ( $fh, $peer_host, $peer_port ) = @_;
        my $handle;
        $handle = AnyEvent::Handle->new(
            fh       => $fh,
            autocork => 1,
            on_error => sub {
                $_[0]->destroy;
                print "connection error\n";
            },
            on_eof => sub {
                $handle->destroy;
            }
        );

        # Create Protocol::HTTP2::Server object
        my $server;
        $server = Protocol::HTTP2::Server->new(
            on_request => sub {
                my ( $stream_id, $headers, $data ) = @_;
                my $message = "hello, world!";

                # Response to client
                $server->response(
                    ':status' => 200,
                    stream_id => $stream_id,

                    # HTTP/1.1 Headers
                    headers   => [
                        'server'         => 'perl-Protocol-HTTP2/0.13',
                        'content-length' => length($message),
                        'cache-control'  => 'max-age=3600',
                        'date'           => 'Fri, 18 Apr 2014 07:27:11 GMT',
                        'last-modified'  => 'Thu, 27 Feb 2014 10:30:37 GMT',
                    ],

                    # Content
                    data => $message,
                );
            },
        );

        # First send settings to peer
        while ( my $frame = $server->next_frame ) {
            $handle->push_write($frame);
        }

        # Receive clients frames
        # Reply to client
        $handle->on_read(
            sub {
                my $handle = shift;

                $server->feed( $handle->{rbuf} );

                $handle->{rbuf} = undef;
                while ( my $frame = $server->next_frame ) {
                    $handle->push_write($frame);
                }
                $handle->push_shutdown if $server->shutdown;
            }
        );
    };

    $w->recv;

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

See also Shuvgey <https://github.com/vlet/Shuvgey> - AnyEvent HTTP/2 Server for PSGI based on Protocol::HTTP2::Server.

  METHODS
new

Initialize new server object

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

Available options:

on_request => sub {...}
    Callback invoked when receiving client's requests

        on_request => sub {
            # Stream ID, headers array reference and body of request
            my ( $stream_id, $headers, $data ) = @_;

            my $message = "hello, world!";
            $server->response(
                ':status' => 200,
                stream_id => $stream_id,
                headers   => [
                    'server'         => 'perl-Protocol-HTTP2/0.13',
                    'content-length' => length($message),
                ],
                data => $message,
            );
            ...
        },

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.

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

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 ) = @_;
            ...
        },

response

Prepare response

    my $message = "hello, world!";
    $server->response(

        # HTTP/2 status
        ':status' => 200,

        # Stream ID
        stream_id => $stream_id,

        # HTTP/1.1 headers
        headers   => [
            'server'         => 'perl-Protocol-HTTP2/0.01',
            'content-length' => length($message),
        ],

        # Body of response
        data => $message,
    );

response_stream

If body of response is not yet ready or server will stream data

    # P::H::Server::Stream object
    my $server_stream;
    $server_stream = $server->response_stream(

        # HTTP/2 status
        ':status' => 200,

        # Stream ID
        stream_id => $stream_id,

        # HTTP/1.1 headers
        headers   => [
            'server'         => 'perl-Protocol-HTTP2/0.01',
        ],

        # Callback if client abort this stream
        on_cancel => sub {
            ...
        }
    );

    # Send partial data
    $server_stream->send($chunk_of_data);
    $server_stream->send($chunk_of_data);

    ## 3 ways to finish stream:
    #
    # The best: send last chunk and close stream in one action
    $server_stream->last($chunk_of_data);

    # Close the stream (will send empty frame)
    $server_stream->close();

    # Destroy object (will send empty frame)
    undef $server_stream

push

Prepare Push Promise. See Server Push <https://tools.ietf.org/html/rfc7540#section-8.2>

    # Example of push inside of on_request callback
    on_request => sub {
        my ( $stream_id, $headers, $data ) = @_;
        my %h = (@$headers);

        # Push promise (must be before response)
        if ( $h{':path'} eq '/index.html' ) {

            # index.html contain styles.css resource, so server can push
            # "/style.css" to client before it request it to increase speed
            # of loading of whole page
            $server->push(
                ':authority' => 'localhost:8000',
                ':method'    => 'GET',
                ':path'      => '/style.css',
                ':scheme'    => 'http',
                stream_id    => $stream_id,
            );
        }

        $server->response(...);
        ...
    }

shutdown

Get connection status:

0 - active
1 - closed (you can terminate connection)

next_frame

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

undef - on error
0 - nothing to send
binary string - encoded frame

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

feed

Feed decoder with chunks of client's request

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

ping

Send ping frame to client (to keep connection alive)

    $server->ping

or

    $server->ping($payload);

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