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

Psr7 Laravel Package

guzzlehttp/psr7

Full PSR-7 message implementation with rich stream support: multiple stream types and decorators (append, buffer, caching, etc.), plus helpers like query-string parsing. Installed via Composer and maintained with v2 for PHP 7.2.5+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require guzzlehttp/psr7
    

    Ensure your composer.json targets PHP 7.2.5+ (for v2.x).

  2. First Use Case: Create a PSR-7 request/response with minimal boilerplate:

    use GuzzleHttp\Psr7\Request;
    use GuzzleHttp\Psr7\Response;
    
    $request = new Request('GET', 'https://api.example.com/data');
    $response = new Response(200, [], '{"status": "success"}');
    
  3. Key Entry Points:

    • Utils::streamFor(): Convert strings/resources to streams.
    • Message::toString(): Debug HTTP messages.
    • Stream decorators (e.g., AppendStream, LimitStream) for common operations.

Implementation Patterns

Core Workflows

  1. Request/Response Handling:

    // Build a request with headers/body
    $request = new Request('POST', '/upload', [
        'Content-Type' => 'application/json',
    ], json_encode(['file' => 'data.txt']));
    
    // Parse a raw response
    $response = Message::parseResponse($rawHttpString);
    
  2. Stream Manipulation:

    • Concatenate streams:
      $stream = new AppendStream([
          Utils::streamFor('Part 1'),
          Utils::streamFor('Part 2'),
      ]);
      
    • Chunk uploads:
      $fileStream = Utils::streamFor(fopen('large_file.zip', 'r'));
      $chunked = new LimitStream($fileStream, 1024 * 1024); // 1MB chunks
      
  3. Query/URI Utilities:

    // Parse query strings
    $params = Query::parse('foo=bar&baz[]=1&baz[]=2');
    
    // Build URIs
    $uri = Message::parseRequestUri('/search', ['query' => 'q=test']);
    
  4. Debugging/Inspection:

    // Log request/response details
    echo Message::toString($request);
    echo Message::bodySummary($response); // Truncated body preview
    

Integration Tips

  • With Guzzle HTTP Client: Use PSR-7 messages directly as request/response objects in Guzzle:
    $client = new \GuzzleHttp\Client();
    $response = $client->send($request, ['http_errors' => false]);
    
  • File Uploads:
    $fileStream = new LazyOpenStream('/path/to/file', 'r');
    $request = new Request('PUT', '/upload', [], $fileStream);
    
  • Stream Decorators: Chain decorators for complex behavior (e.g., logging + compression):
    $stream = new InflateStream(
        new LoggingStream($originalStream, fn($data) => logger($data))
    );
    

Gotchas and Tips

Pitfalls

  1. Stream Ownership:

    • PSR-7 streams are not PHP resources. Closing a PHP resource (e.g., fclose()) does not close the stream. Use StreamInterface::close() explicitly.
    • Fix: Always call $stream->close() when done.
  2. Non-Seekable Streams:

    • Decorators like CachingStream or LimitStream may fail on non-seekable streams (e.g., sockets, php://input).
    • Fix: Wrap in CachingStream if seeking is needed:
      $stream = new CachingStream(fopen('php://input', 'r'));
      
  3. Memory Leaks:

    • BufferStream/CachingStream hold data in memory. Avoid large buffers in long-running processes.
    • Fix: Use DroppingStream or LimitStream to cap memory usage.
  4. Query String Parsing:

    • Query::parse() does not handle nested arrays (e.g., foo[bar]=1 becomes 'foo[bar]').
    • Fix: Pre-process arrays or use http_build_query() for nested data.
  5. Deprecated Methods:

    • Header::normalize() is deprecated. Use Header::splitList() instead.

Debugging Tips

  • Inspect Stream Metadata:
    $metadata = $stream->getMetadata();
    var_dump($metadata['seekable'], $metadata['readable']);
    
  • Check for EOF:
    if ($stream->eof()) {
        // Handle end-of-stream
    }
    
  • Stream Decorator Debugging: Override read()/write() in a custom decorator to log calls:
    class DebugStream implements StreamInterface {
        use StreamDecoratorTrait;
        public function read($length) {
            echo "Reading {$length} bytes...\n";
            return $this->stream->read($length);
        }
    }
    

Extension Points

  1. Custom Stream Decorators: Use StreamDecoratorTrait to create lightweight decorators:

    class TimingStream implements StreamInterface {
        use StreamDecoratorTrait;
        private $start;
        public function read($length) {
            $this->start ??= microtime(true);
            return $this->stream->read($length);
        }
        public function getReadTime() {
            return microtime(true) - $this->start;
        }
    }
    
  2. Stream Wrapper: Convert PSR-7 streams to PHP resources for interop:

    $resource = StreamWrapper::getResource($stream);
    $data = fread($resource, 1024);
    
  3. Query/URI Utilities: Extend Query::build() for custom encoding (e.g., RFC 3986 vs. default):

    $query = Query::build(['page' => 1], PHP_QUERY_RFC3986);
    
  4. Message Modification: Use Utils::modifyRequest() to avoid deep cloning:

    $modified = Utils::modifyRequest($request, [
        'set_headers' => ['Authorization' => 'Bearer token'],
        'body' => Utils::streamFor('new body'),
    ]);
    

Performance Quirks

  • Utils::copyToString(): Avoid for large streams (>1MB). Use Utils::copyToStream() with a file stream instead.
  • AppendStream: Seeking is not supported. Use LimitStream for random access.
  • PumpStream: Callables must return false on EOF. Omitting this can cause hangs.
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