NAME

Plack::Handler::H2 - High-performance HTTP/2 server handler for Plack

SYNOPSIS

Create a PSGI application file (app.psgi):

my $app = sub {
    my $env = shift;
    return [
        200,
        ['Content-Type' => 'text/plain'],
        ['Hello, HTTP/2 World!']
    ];
};

Run with plackup:

# With custom certificates
plackup -s H2 \
    --ssl-cert-file=/path/to/server.crt \
    --ssl-key-file=/path/to/server.key \
    --port=8443 \
    app.psgi

# Development mode (auto-generates self-signed certificate)
plackup -s H2 --port=8443 app.psgi

DESCRIPTION

Plack::Handler::H2 is a production-ready PSGI/Plack handler that implements HTTP/2 server functionality using native C++ code with Perl XS bindings. It leverages industry-standard libraries (nghttp2, libevent, OpenSSL) to provide efficient, asynchronous HTTP/2 request handling with TLS/SSL support.

This handler is designed to be used with plackup for most use cases. Direct instantiation is only recommended for advanced scenarios where plackup cannot be used.

FEATURES

  • Full HTTP/2 Protocol Support

    Complete HTTP/2 implementation using nghttp2 with header compression (HPACK), stream multiplexing, server push capabilities, and flow control.

  • TLS/SSL Required

    Secure connections with OpenSSL, including ALPN (Application-Layer Protocol Negotiation). Supports OpenSSL 1.1.1+ and 3.0+. Automatically generates self-signed certificates for development.

  • Streaming Responses

    Full support for PSGI streaming and delayed responses, including chunked transfer without Content-Length, progressive rendering, and server-sent events compatibility.

  • Asynchronous I/O

    Event-driven architecture using libevent2 with non-blocking request handling, concurrent stream processing, and efficient memory management for large request bodies.

  • High Performance

    Native C++ implementation with minimal overhead, automatic buffering strategy for request bodies (memory for small, temp files for large), and HTTP/2 header compression.

  • PSGI Compliant

    Full compatibility with PSGI specification and works with any PSGI-compatible framework including Dancer2, Mojolicious::Lite, and custom PSGI applications.

CONFIGURATION

When using plackup, configuration is provided via command-line options:

SSL/TLS Options

--ssl-cert-file (optional)

Path to SSL certificate file in PEM format. If not provided, a self-signed certificate is automatically generated for development use.

--ssl-key-file (optional)

Path to SSL private key file in PEM format. Required if --ssl-cert-file is provided.

Server Options

--host (optional, default: 0.0.0.0)

IP address to bind to.

--port (optional, default: 5000)

Port number to listen on.

--timeout (optional, default: 120)

General timeout in seconds.

--read-timeout (optional, default: 60)

Read timeout in seconds.

--write-timeout (optional, default: 60)

Write timeout in seconds.

--request-timeout (optional, default: 30)

Request timeout in seconds.

--max-request-body-size (optional, default: 10485760)

Maximum request body size in bytes (default is 10MB).

Example with Custom Configuration

plackup -s H2 \
    --host=127.0.0.1 \
    --port=8443 \
    --ssl-cert-file=server.crt \
    --ssl-key-file=server.key \
    --max-request-body-size=20971520 \
    app.psgi

METHODS

new

my $handler = Plack::Handler::H2->new(%options);

Creates a new handler instance. This is typically called by plackup and rarely needs to be called directly.

Options:

  • ssl_cert_file - Path to SSL certificate file

  • ssl_key_file - Path to SSL private key file

  • host - IP address to bind to

  • port - Port number to listen on

  • timeout - General timeout in seconds

  • read_timeout - Read timeout in seconds

  • write_timeout - Write timeout in seconds

  • request_timeout - Request timeout in seconds

  • max_request_body_size - Maximum request body size in bytes

run

$handler->run($app);

Runs the PSGI application with the configured options. This method starts the HTTP/2 server and enters the event loop. It will not return until the server is shut down.

Parameters:

  • $app - A PSGI application code reference

STREAMING RESPONSES

Plack::Handler::H2 fully supports PSGI streaming responses using the delayed response pattern. This is useful for:

  • Large responses that don't fit in memory

  • Server-sent events

  • Progressive rendering

  • Long-polling

Streaming Example

my $app = sub {
    my $env = shift;
    
    return sub {
        my $responder = shift;
        
        # Send headers and get writer
        my $writer = $responder->([
            200,
            ['Content-Type' => 'text/html']
        ]);
        
        # Stream data in chunks
        $writer->write("<html><body>");
        $writer->write("<h1>Streaming Response</h1>");
        sleep 1;  # Simulate processing
        $writer->write("<p>This data arrives progressively.</p>");
        $writer->write("</body></html>");
        
        # Close the stream
        $writer->close();
    };
};

The writer object is an instance of Plack::Handler::H2::Writer which provides write() and close() methods for sending data chunks.

SSL/TLS CONFIGURATION

Production Use

For production, obtain valid certificates from a trusted Certificate Authority:

# Using Let's Encrypt (example)
certbot certonly --standalone -d yourdomain.com

Then run with plackup:

plackup -s H2 \
    --ssl-cert-file=/etc/letsencrypt/live/yourdomain.com/fullchain.pem \
    --ssl-key-file=/etc/letsencrypt/live/yourdomain.com/privkey.pem \
    --port=443 \
    --host=0.0.0.0 \
    app.psgi

Development Use

For development and testing, simply run plackup without certificate options to auto-generate self-signed certificates:

plackup -s H2 --port=8443 app.psgi

Or generate your own self-signed certificate:

openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt \
    -days 365 -nodes -subj "/CN=localhost"

plackup -s H2 \
    --ssl-cert-file=server.crt \
    --ssl-key-file=server.key \
    --port=8443 \
    app.psgi

Note: Browsers will display security warnings for self-signed certificates. You'll need to accept the security exception to proceed.

SYSTEM REQUIREMENTS

System Libraries

  • nghttp2 - HTTP/2 C library (version 1.x)

  • libevent2 - Event notification library (version 2.x)

  • OpenSSL - TLS/SSL cryptographic library (version 1.1.1 or 3.0+)

  • C++ Compiler - GCC 7+, Clang 5+, or equivalent with C++17 support

Installation of Dependencies

Ubuntu/Debian:

sudo apt-get install libnghttp2-dev libevent-dev libssl-dev g++ make

CentOS/RHEL:

sudo yum install nghttp2-devel libevent-devel openssl-devel gcc-c++ make

macOS:

brew install nghttp2 libevent openssl

Perl Requirements

  • Perl 5.024 or higher with XS support

  • Plack 1.0+

  • File::Temp 0.22+

  • XSLoader (core module)

PLATFORM SUPPORT

Supported operating systems:

  • Linux (Ubuntu, Debian, CentOS, RHEL, etc.)

  • macOS

  • FreeBSD

  • OpenBSD

Windows: Not currently supported due to libevent requirements.

ARCHITECTURE

The module consists of three main layers:

1. H2.pm - High-level Perl interface

PSGI handler implementation, configuration management, self-signed certificate generation, and streaming response coordination.

2. H2.xs - XS bindings layer

Efficient Perl-to-C++ interface, type conversion and marshalling, and function wrappers for core operations.

3. plack_handler_h2.cc/h - Core C++ implementation

nghttp2 integration for HTTP/2 protocol, libevent event loop for async I/O, OpenSSL for TLS/SSL and ALPN, request/response handling, stream multiplexing, and memory-efficient body handling (auto-switches to temp files for large bodies).

PERFORMANCE

The handler is designed for high performance:

  • Native C++ implementation minimizes overhead

  • Asynchronous I/O prevents blocking

  • Stream multiplexing allows concurrent request processing

  • Automatic buffering strategy (memory for small bodies, temp files for large)

  • HTTP/2 header compression reduces bandwidth

See the benchmark/ directory in the distribution for benchmarking tools to compare with other Plack handlers.

TROUBLESHOOTING

"Could not create SSL_CTX"

  • Verify OpenSSL is properly installed

  • Check that certificate and key files are readable

  • Ensure certificate and key match

"Could not read certificate file" / "Could not read private key file"

  • Verify file paths are correct and absolute

  • Check file permissions (should be readable by the process)

  • Ensure files are in PEM format

  • Check for proper line endings (UNIX style)

Connection refused / Connection errors

  • Verify the server is listening on the correct address and port

  • Check firewall settings

  • Ensure no other service is using the same port

  • For localhost testing, try https://localhost:PORT (not http://)

Browser shows "NET::ERR_CERT_AUTHORITY_INVALID"

This is normal for self-signed certificates. Click "Advanced" and "Proceed to localhost (unsafe)" to continue. For production, use certificates from a trusted CA.

Large request bodies failing

Adjust --max-request-body-size parameter (default 10MB). The handler automatically uses temp files for bodies larger than 1MB.

EXAMPLES

The example/ directory in the distribution contains several working examples:

  • example.pl - Basic PSGI app with form handling

  • example_streamed.pl - Streaming response demonstration

  • example_streamed_2.pl - Delayed response pattern

  • example_dancer2.pl - Dancer2 framework integration

  • example_mojo.pl - Mojolicious::Lite integration

SEE ALSO

VERSION

Version 0.0.1

REPOSITORY

https://github.com/rawleyfowler/perl-Plack-Handler-H2

Report bugs and issues at: https://github.com/rawleyfowler/perl-Plack-Handler-H2/issues

AUTHOR

Rawley Fowler <rawley@molluscsoftware.com>

LICENSE

This software is released under the BSD 3-Clause License. See the LICENSE file in the distribution for details.

ACKNOWLEDGMENTS

Built with:

  • nghttp2 for HTTP/2 protocol implementation

  • libevent for asynchronous I/O

  • OpenSSL for TLS/SSL security

Special thanks to the Plack community and all contributors.