php-http/message
PSR-7 HTTP message utilities for PHP: authentication implementations, stream encoders, message decorators, cookie handling, request matchers, and PSR-7 factory adapters for Guzzle and Diactoros—handy building blocks for HTTP clients and workflows.
Start by installing the package: composer require php-http/message. Its core value lies in PSR-7 interoperability—providing common implementations, decorators, and utilities to manipulate HTTP messages without locking into a specific HTTP client library. The most immediately useful features for day-to-day work include:
FullHttpMessageFormatter, CurlCommandFormatter) for debugging—turning PSR-7 messages into readable logs or copy-pasteable cURL commands.Cookie class for parsing/setting cookies with path/domain/security validation.Check out the official documentation for quick-start examples, especially the formatter and authentication sections.
Debugging with formatters: Inject FullHttpMessageFormatter or CurlCommandFormatter in your HTTP client wrappers or middleware to log full requests/responses. Use formatResponseForRequest() (the recommended method) to include contextual cues from the request (e.g., only dump the response body when the request body was safe to log).
$formatter = new FullHttpMessageFormatter(8192, FullHttpMessageFormatter::SHOW_ALL);
$log = $formatter->formatResponseForRequest($response, $request);
Authentication decorators: Attach auth metadata to requests using decorators like RequestDecorator with an Authentication implementation:
$auth = new Bearer('your-token');
$request = (new RequestDecorator($request))->withAuthentication($auth);
Stream utilities: Use BufferedStream to add seekability to non-seekable streams (e.g., gzip-compressed responses) so they can be read multiple times. Use FilteredStream to transform content on-the-fly (e.g., gzip/decompress, censor sensitive fields)—just ensure your source stream implements isSeekable() correctly.
Factory fallback: While deprecated, GuzzleStreamFactory, DiactorosStreamFactory, etc., let you instantiate PSR-7 streams without caring which client you’re using—ideal for polyfills during migration.
Cookie matching & parsing: Use Cookie::parseHeader() to parse Set-Cookie headers, then use Cookie::matchPath(), matchDomain(), matchSecure() for client-side cookie logic.
PSR-7 2.0 compatibility: Since 1.15+, the package declares compatibility with both PSR-7 1.x and 2.x, but decorator classes may require minor adjustments—ensure your types match exactly (e.g., return types like string|null vs string). Update dependencies to avoid type conflicts.
Binary stream detection: FullHttpMessageFormatter and CurlCommandFormatter omit binary bodies by default (showing [binary stream omitted]). You can tweak the binary regex via FullHttpMessageFormatter::setBinaryDetectionRegex() if your content is misidentified as binary.
Stream seekability is critical: Many formatter/stream utilities rely on isSeekable() and rewind(). Non-seekable streams will either be skipped (formatters) or cause warnings (FilteredStream uses @trigger_error instead of exceptions). Always ensure your source streams support seeking or wrap them with BufferedStream.
Factory deprecation landmines: The package no longer depends on php-http/message-factory. Httplug-style factories (e.g., GuzzleMessageFactory) are deprecated. Prefer using the PSR-17 factories shipped with your HTTP client instead.
Migration caveats: If upgrading from older versions:
Zend\Diactoros references with Laminas\Diactoros—but the bridge handles most BC for now.formatResponse() → formatResponseForRequest().FilteredStream::getReadFilter()—they were internal and removed.Testing tip: Use CurlCommandFormatter to generate cURL snippets for reproducing API calls during debugging or integration tests:
$curl = (new CurlCommandFormatter())->format($request);
file_put_contents('debug_request.sh', $curl);
Path/Domain cookie matching: Cookie::matchPath('/') now correctly matches all paths—including root /. Earlier versions had a bug where / wouldn’t match /cookie; this was fixed in 1.4.1.
WSSE hashing algorithm: In 1.11.0+, specify sha256, sha512, etc., explicitly when creating WsseAuthentication—the default may not be what you expect.
Performance: Avoid formatting large streams repeatedly; caching formatted output or truncating with $maxBodyLength helps. 0 bytes in BufferedStream no longer throws—v1.16.2+ is safer for streaming edge cases.
How can I help you explore Laravel packages today?