Scroll to navigation

Protocol::HTTP2::Server(3pm) User Contributed Perl Documentation 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:

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

Callback invoked on protocol errors

    on_error => sub {
        my $error = shift;
        ...
    },
    
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:

0 - nothing to send

    # 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.

2024-07-03 perl v5.40.0