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 specifies "guzzlehttp/psr7": "^2.0".

  2. First Use Case: Create a basic HTTP request/response using PSR-7 interfaces:

    use GuzzleHttp\Psr7\Request;
    use GuzzleHttp\Psr7\Response;
    
    // Create a request
    $request = new Request('GET', 'https://api.example.com/data');
    
    // Create a response (simulated)
    $response = new Response(200, [], '{"status": "success"}');
    
    // Use with a client (e.g., Guzzle HTTP client)
    $client = new \GuzzleHttp\Client();
    $result = $client->send($request);
    
  3. Key Classes to Know:

    • Request, Response: Core HTTP message implementations.
    • StreamInterface: PSR-7 stream abstraction (e.g., AppendStream, BufferStream).
    • Utils: Helper methods for common tasks (e.g., streamFor(), copyToString()).
  4. Where to Look First:

    • PSR-7 Specification for interface contracts.
    • GuzzleHttp\Psr7\Utils for utility functions.
    • Stream decorators (e.g., AppendStream, LimitStream) for advanced use cases.

Implementation Patterns

Core Workflows

1. HTTP Message Handling

  • Request/Response Creation:
    $request = new Request('POST', '/upload', [
        'Content-Type' => 'application/json',
    ], json_encode(['file' => 'data.bin']));
    
  • Modifying Messages: Use Utils::modifyRequest() to avoid cloning:
    $modified = Utils::modifyRequest($request, [
        'set_headers' => ['Authorization' => 'Bearer token123'],
        'body' => Utils::streamFor('new-data'),
    ]);
    

2. Stream Manipulation

  • Composing Streams: Combine multiple streams (e.g., file + in-memory data):
    $fileStream = Utils::streamFor(fopen('large_file.bin', 'r'));
    $appendStream = new AppendStream([$fileStream, Utils::streamFor('extra-data')]);
    
  • Chunked Uploads: Use LimitStream to split large files:
    $original = Utils::streamFor(fopen('huge_file.bin', 'r'));
    $chunk = new LimitStream($original, 5 * 1024 * 1024, 0); // 5MB chunks
    

3. Query String Handling

  • Parsing/Building:
    $query = Query::parse('foo=bar&baz[]=1&baz[]=2');
    // ['foo' => 'bar', 'baz' => ['1', '2']]
    
    $built = Query::build(['foo' => 'bar', 'baz' => [1, 2]]);
    // 'foo=bar&baz=1&baz=2'
    

4. Stream Decorators

  • Custom Logic: Extend streams with StreamDecoratorTrait:
    class LoggingStream implements StreamInterface {
        use StreamDecoratorTrait;
        public function read($length) {
            $data = $this->stream->read($length);
            logger()->debug("Read {$length} bytes: " . substr($data, 0, 20));
            return $data;
        }
    }
    

5. Integration with Guzzle HTTP Client

  • Async Requests:
    $promise = $client->sendAsync($request);
    $promise->then(function (Response $response) {
        $body = Utils::copyToString($response->getBody());
    });
    

Integration Tips

  1. Leverage Utils for Common Tasks:

    • Convert resources to streams: Utils::streamFor($resource).
    • Copy streams efficiently: Utils::copyToStream($source, $dest).
  2. Handle Large Data:

    • Use BufferStream to control memory usage:
      $buffered = new BufferStream(1024); // 1KB buffer
      
  3. Debugging Streams:

    • Use CachingStream for non-seekable streams (e.g., HTTP redirects):
      $stream = new CachingStream($nonSeekableStream);
      
  4. Multipart Uploads:

    • Combine streams for multipart/form-data:
      $multipart = new MultipartStream([
          ['name' => 'file', 'contents' => $fileStream],
          ['name' => 'description', 'contents' => 'Uploaded via API'],
      ]);
      
  5. Testing:

    • Mock streams with FnStream for unit tests:
      $mockStream = FnStream::decorate($stream, [
          'read' => function () { return 'mocked-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. Seekable vs. Non-Seekable Streams:

    • Some streams (e.g., PumpStream, FnStream) may not support seeking. Check isSeekable() before calling seek().
    • Fix: Use CachingStream to wrap non-seekable streams if seeking is required.
  3. Memory Leaks:

    • BufferStream and CachingStream buffer data in memory. Monitor memory usage for large streams.
    • Fix: Set appropriate buffer sizes (e.g., BufferStream(1024)).
  4. Query String Parsing:

    • Query::parse() does not handle nested arrays (e.g., foo[a]=1&foo[b]=2 becomes ['foo[a]' => '1'], not ['foo' => ['a' => '1']]).
    • Fix: Pre-process nested data or use a custom parser.
  5. Stream Decorator Order:

    • Decorators are applied from outer to inner. The outermost decorator is the first to receive calls.
    • Example:
      $stream = new LimitStream(new LoggingStream($originalStream));
      // LoggingStream is inner; LimitStream is outer.
      
  6. UTF-8 Headers:

    • Headers must be UTF-8 encoded. Non-UTF-8 values may cause issues.
    • Fix: Use mb_convert_encoding() if needed.
  7. Deprecated Methods:

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

Debugging Tips

  1. Inspect Stream Contents:

    • Use Utils::copyToString($stream) to dump stream contents (be cautious with large streams).
  2. Check Stream Metadata:

    • Access metadata via $stream->getMetadata() to debug issues (e.g., buffer sizes, seekability).
  3. Enable Guzzle Debugging:

    • Add debug middleware to log requests/responses:
      $client->getConfig(['debug' => fopen('debug.log', 'w')]);
      
  4. Validate PSR-7 Compliance:

    • Use tools like PHPStan with PSR-7 rules to catch interface violations early.

Extension Points

  1. Custom Stream Decorators:

    • Extend StreamDecoratorTrait for reusable stream logic (e.g., compression, encryption).
  2. Stream Wrappers:

    • Use StreamWrapper::getResource() to integrate with PHP’s stream functions (e.g., fopen(), fread()).
  3. Message Parsing:

    • Override Message::parseRequest() or Message::parseResponse() for custom message formats.
  4. Query String Customization:

    • Extend Query::build() or Query::parse() for domain-specific query handling.
  5. Event-Driven Streams:

    • Combine PumpStream with callbacks for event-driven processing:
      $pumpStream = new PumpStream(function ($length) {
          return $generator->current() ?: false;
      });
      
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony