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+.
Installation:
composer require guzzlehttp/psr7
Ensure your composer.json specifies "guzzlehttp/psr7": "^2.0".
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);
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()).Where to Look First:
GuzzleHttp\Psr7\Utils for utility functions.AppendStream, LimitStream) for advanced use cases.$request = new Request('POST', '/upload', [
'Content-Type' => 'application/json',
], json_encode(['file' => 'data.bin']));
Utils::modifyRequest() to avoid cloning:
$modified = Utils::modifyRequest($request, [
'set_headers' => ['Authorization' => 'Bearer token123'],
'body' => Utils::streamFor('new-data'),
]);
$fileStream = Utils::streamFor(fopen('large_file.bin', 'r'));
$appendStream = new AppendStream([$fileStream, Utils::streamFor('extra-data')]);
LimitStream to split large files:
$original = Utils::streamFor(fopen('huge_file.bin', 'r'));
$chunk = new LimitStream($original, 5 * 1024 * 1024, 0); // 5MB chunks
$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'
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;
}
}
$promise = $client->sendAsync($request);
$promise->then(function (Response $response) {
$body = Utils::copyToString($response->getBody());
});
Leverage Utils for Common Tasks:
Utils::streamFor($resource).Utils::copyToStream($source, $dest).Handle Large Data:
BufferStream to control memory usage:
$buffered = new BufferStream(1024); // 1KB buffer
Debugging Streams:
CachingStream for non-seekable streams (e.g., HTTP redirects):
$stream = new CachingStream($nonSeekableStream);
Multipart Uploads:
$multipart = new MultipartStream([
['name' => 'file', 'contents' => $fileStream],
['name' => 'description', 'contents' => 'Uploaded via API'],
]);
Testing:
FnStream for unit tests:
$mockStream = FnStream::decorate($stream, [
'read' => function () { return 'mocked-data'; },
]);
Stream Ownership:
fclose()) does not close the stream. Use StreamInterface::close() explicitly.$stream->close() when done.Seekable vs. Non-Seekable Streams:
PumpStream, FnStream) may not support seeking. Check isSeekable() before calling seek().CachingStream to wrap non-seekable streams if seeking is required.Memory Leaks:
BufferStream and CachingStream buffer data in memory. Monitor memory usage for large streams.BufferStream(1024)).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']]).Stream Decorator Order:
$stream = new LimitStream(new LoggingStream($originalStream));
// LoggingStream is inner; LimitStream is outer.
UTF-8 Headers:
mb_convert_encoding() if needed.Deprecated Methods:
Header::normalize() is deprecated. Use Header::splitList() instead.Inspect Stream Contents:
Utils::copyToString($stream) to dump stream contents (be cautious with large streams).Check Stream Metadata:
$stream->getMetadata() to debug issues (e.g., buffer sizes, seekability).Enable Guzzle Debugging:
$client->getConfig(['debug' => fopen('debug.log', 'w')]);
Validate PSR-7 Compliance:
Custom Stream Decorators:
StreamDecoratorTrait for reusable stream logic (e.g., compression, encryption).Stream Wrappers:
StreamWrapper::getResource() to integrate with PHP’s stream functions (e.g., fopen(), fread()).Message Parsing:
Message::parseRequest() or Message::parseResponse() for custom message formats.Query String Customization:
Query::build() or Query::parse() for domain-specific query handling.Event-Driven Streams:
PumpStream with callbacks for event-driven processing:
$pumpStream = new PumpStream(function ($length) {
return $generator->current() ?: false;
});
How can I help you explore Laravel packages today?