Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Hpack Laravel Package

amphp/hpack

Fast HPACK (HTTP/2 header compression) implementation for PHP by amphp. Provides efficient encoding/decoding of header blocks with dynamic tables, Huffman coding, and compliance-focused behavior, suitable for high-performance HTTP/2 clients and servers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require amphp/hpack
    

    Ensure PHP ≥ 7.4 (PHP 8.x recommended).

  2. First Use Case: Encode/decode HTTP/2 headers for a custom HTTP/2 server or client (e.g., using amphp/http-server).

    use Amp\Hpack\Encoder;
    use Amp\Hpack\Decoder;
    
    $encoder = new Encoder();
    $decoder = new Decoder();
    
    // Encode headers (e.g., from Laravel's request)
    $headers = [
        [':method', 'GET'],
        [':path', '/api/users'],
        ['content-type', 'application/json'],
    ];
    $encoded = $encoder->encode($headers); // Binary string
    
    // Decode headers (e.g., for a custom response)
    $decoded = $decoder->decode($encoded); // Array of [name, value] pairs
    
  3. Where to Look First:

    • Core Classes: Encoder (compression) and Decoder (decompression) in src/Encoder.php and src/Decoder.php.
    • Configuration: Constructor options like tableSizeLimit (default: 4096 bytes).
    • Examples: examples/ directory for basic usage (e.g., roundtrip.php).
    • Tests: tests/ for edge cases (e.g., RfcTest.php for RFC 7541 compliance).

Implementation Patterns

Workflows

  1. Per-Connection State: Reuse Encoder/Decoder instances for the lifetime of an HTTP/2 connection (HPACK’s dynamic table is stateful).

    // In a custom HTTP/2 server loop
    $encoder = new Encoder();
    $decoder = new Decoder();
    
    foreach ($requests as $request) {
        $encodedHeaders = $encoder->encode($request->headers);
        // Send $encodedHeaders via HTTP/2 frame...
    }
    
  2. Integration with Async I/O: Use with amphp/socket or ReactPHP for async HTTP/2 servers/clients. Example with amphp/http-server:

    use Amp\Http\Server\Request;
    use Amp\Http\Server\Response;
    
    $server = new Server('127.0.0.1', 8080);
    $encoder = new Encoder();
    
    $server->on('request', function (Request $request) use ($encoder) {
        $response = new Response();
        $response->setHeader(':status', '200');
        $response->setHeader('content-type', 'text/plain');
    
        $encodedHeaders = $encoder->encode($response->getHeaders());
        // Write $encodedHeaders to HTTP/2 frame...
    });
    
  3. Dynamic Table Management:

    • Table Size: Set via constructor (e.g., new Decoder(64 * 1024) for 64KB limit).
    • Updates: Handle SETTINGS_HEADER_TABLE_SIZE frames by calling decoder->setTableSizeLimit().
      $decoder->setTableSizeLimit(1024); // Update after receiving SETTINGS frame
      
  4. Header Normalization: HPACK requires headers to be lowercase and canonicalized (e.g., :method instead of :Method). Use Laravel’s Str::lower() or HeaderUtils for preprocessing:

    $normalizedHeaders = array_map(
        fn(array $header) => [strtolower($header[0]), $header[1]],
        $headers
    );
    
  5. Testing: Validate against RFC 7541 test vectors (included in tests/RfcTest.php). Example:

    $this->assertEquals(
        $decoder->decode($encoder->encode($headers)),
        $headers
    );
    

Laravel-Specific Tips

  • Proxy Use Case: If Laravel sits behind an HTTP/2 proxy (e.g., Nginx), do not use this package. HPACK is handled by the proxy.
  • Custom Middleware: For custom HTTP/2 clients (e.g., using amphp/http-client), integrate HPACK after Laravel’s default stack:
    // In a custom HTTP client (not Laravel's Guzzle)
    $client = new AmpHttpClient();
    $encoder = new Encoder();
    
    $response = $client->request('GET', 'https://api.example.com', [
        'headers' => $encoder->encode([[':authority', 'api.example.com']]),
    ]);
    

Gotchas and Tips

Pitfalls

  1. Stateful Dynamic Table:

    • Issue: Forgetting to update the Decoder’s table size after receiving a SETTINGS_HEADER_TABLE_SIZE frame causes corruption.
    • Fix: Always call decoder->setTableSizeLimit() when processing settings frames.
      // Pseudocode for HTTP/2 frame handler
      if ($frame->type === SETTINGS) {
          $decoder->setTableSizeLimit($frame->headerTableSize);
      }
      
  2. Header Name Mismatches:

    • Issue: HPACK is case-sensitive for header names (e.g., :Method vs :method). Laravel’s Request headers may not be normalized.
    • Fix: Preprocess headers to lowercase:
      $hpackHeaders = array_map(
          fn(array $header) => [strtolower($header[0]), $header[1]],
          $request->header->all()
      );
      
  3. Binary Safety:

    • Issue: decode() throws Amp\Http\Server\HttpException on malformed input (e.g., truncated Huffman codes).
    • Fix: Wrap decoding in a try-catch and log raw binary for debugging:
      try {
          $decoded = $decoder->decode($binaryData);
      } catch (HttpException $e) {
          \Log::error("HPACK decode failed", ['binary' => bin2hex($binaryData)]);
          throw $e;
      }
      
  4. Performance Overhead:

    • Issue: HPACK adds CPU overhead. For high-throughput services, benchmark with/without compression.
    • Fix: Disable compression for small headers (adjust compressionThreshold):
      $encoder = new Encoder(compressionThreshold: 2048); // Only compress >2KB headers
      
  5. FFI Dependencies:

    • Issue: The HPackNghttp2 class (optional) requires libnghttp2 and FFI. Missing dependencies cause failures.
    • Fix: Install libnghttp2 via system package manager (e.g., apt-get install libnghttp2-dev) or avoid FFI by using the pure-PHP implementation.

Debugging Tips

  1. Compare with Wireshark: Capture HTTP/2 traffic and compare HPACK-encoded headers with Wireshark’s "HPACK" dissector to spot mismatches.

  2. Enable Debug Logging: Use HPACK_DEBUG (if available) or log raw binary:

    \Log::debug('Encoded headers', ['hex' => bin2hex($encodedHeaders)]);
    
  3. Test Edge Cases:

    • Empty headers: [] → Should encode to empty binary.
    • Large headers: Test with 1MB+ payloads to check compressionThreshold.
    • Duplicate headers: HPACK merges duplicates (e.g., two content-type headers become one).

Extension Points

  1. Custom Header Handling: Extend Encoder/Decoder to modify headers before/after compression:

    class CustomEncoder extends Encoder {
        public function encode(array $headers): string {
            // Redact sensitive headers
            $headers = array_filter($headers, fn(array $h) => $h[0] !== 'authorization');
            return parent::encode($headers);
        }
    }
    
  2. Static Table Overrides: Replace the default static table (RFC 7541 § 4.2) for custom headers:

    $customTable = new StaticTable([
        [':custom-header', 'default-value'],
    ]);
    $encoder = new Encoder(staticTable: $customTable);
    
  3. Huffman Encoding: Override Huffman logic (e.g., for custom Huffman tables) by extending HuffmanEncoder/HuffmanDecoder.

Laravel-Specific Gotchas

  • Guzzle Integration: Laravel’s Guzzle client does not use this package. HPACK is handled by the underlying HTTP/2 stack (e.g., cURL).
  • Middleware Conflicts: Avoid using this package in Laravel’s middleware pipeline. It’s designed for low-level HTTP/2 framing, not HTTP requests/responses.
  • Async vs Synchronous: Laravel’s request lifecycle is synchronous. This package is built for async I/O (e.g., amphp/ReactPHP). Use only in custom async HTTP servers.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope