Plack::Handler::H2

A high-performance HTTP/2 server handler for Plack, built with C++ and utilizing nghttp2, libevent, and OpenSSL.

Test Install

Description

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

Features

Dependencies

System Libraries

Perl Modules

Installation

Install System 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

Build and Install the Module

From CPAN (when available):

cpanm Plack::Handler::H2

From source:

perl Makefile.PL
make
make test
make install

Usage

Basic Example

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

Streaming Response Example

Create a streaming PSGI application (streaming.psgi):

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();
    };
};

Run with plackup:

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

Configuration Options

When using plackup, you can pass options via command-line flags:

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

Note: For programmatic use cases where plackup is not suitable, you can instantiate the handler directly with Plack::Handler::H2->new(), but this is only recommended for advanced use cases.

Architecture

The module consists of three main layers:

  1. H2.pm: High-level Perl interface

    • PSGI handler implementation
    • Configuration management
    • Self-signed certificate generation
    • Streaming response coordination
  2. H2.xs: XS bindings layer

    • Efficient Perl-to-C++ interface
    • Type conversion and marshalling
    • 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
    • Memory-efficient body handling (auto-switches to temp files for large bodies)

Examples

The example/ directory contains several working examples:

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, or Internal Use

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

# Auto-generates self-signed certificate
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.

Performance

The handler is designed for high performance:

Testing

Run the test suite:

make test

Tests cover:

Platform Support

Supported operating systems:

Windows: Not currently supported due to libevent requirements.

Requirements Summary

Version

Current version: 0.0.1

Troubleshooting

"Could not create SSL_CTX"

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

Connection refused / Connection errors

Browser shows "NET::ERR_CERT_AUTHORITY_INVALID"

Large request bodies failing

Roadmap

License

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

Authors

Rawley Fowler rawley@molluscsoftware.com

See Also