diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d296b..cc245f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.9.5] - 2024-07-25 +### Fixed +* Prevent PHP warnings when an HTTP response includes a `Content-Type: application/x-gzip` header, but the content is not actually compressed. This issue also occurred with cached responses, because compressed content is decoded during caching. Upon retrieval from the cache, the header indicated compression, but the content was already decoded. + ## [1.9.4] - 2024-07-24 ### Fixed * When using `HttpLoader::cacheOnlyWhereUrl()` to restrict caching, the filter rule is not only applied when adding newly loaded responses to the cache, but also for using cached responses. Example: a response for `https://www.example.com/foo` is already available in the cache, but `$loader->cacheOnlyWhereUrl(Filter::urlPathStartsWith('/bar/'))` was called, the cached response is not used. diff --git a/src/Steps/Loading/Http.php b/src/Steps/Loading/Http.php index ed9ed63..086142f 100644 --- a/src/Steps/Loading/Http.php +++ b/src/Steps/Loading/Http.php @@ -89,9 +89,17 @@ public static function getBodyString(MessageInterface|RespondedRequest $message) $contents = $message->getBody()->getContents(); - if (in_array('application/x-gzip', $message->getHeader('Content-Type'), true)) { + if (in_array('application/x-gzip', $message->getHeader('Content-Type'), true) && function_exists('gzdecode')) { + // Temporarily set a new error handler, so decoding a string that actually isn't compressed, doesn't + // generate a warning. + $previousHandler = set_error_handler(function ($errno, $errstr) { + return $errno === E_WARNING && str_contains($errstr, 'gzdecode(): data error'); + }); + $decoded = gzdecode($contents); + set_error_handler($previousHandler); + $contents = $decoded === false ? $contents : $decoded; } diff --git a/tests/Steps/Loading/HttpTest.php b/tests/Steps/Loading/HttpTest.php index 2e766e4..85a9899 100644 --- a/tests/Steps/Loading/HttpTest.php +++ b/tests/Steps/Loading/HttpTest.php @@ -16,6 +16,7 @@ use Psr\Http\Message\RequestInterface; use stdClass; +use function tests\helper_getRespondedRequest; use function tests\helper_invokeStepWithInput; use function tests\helper_traverseIterable; @@ -405,3 +406,32 @@ function ($key) { helper_invokeStepWithInput($step, $inputArray); }); + +test( + 'the getBodyString() method does not generate a warning, when the response contains a ' . + 'Content-Type: application/x-gzip header, but the content actually isn\'t compressed', + function () { + $warnings = []; + + $previousHandler = set_error_handler(function ($errno, $errstr) use (&$warnings) { + if ($errno === E_WARNING) { + $warnings[] = $errstr; + } + + return false; + }); + + $response = helper_getRespondedRequest( + url: 'https://example.com/yolo', + responseHeaders: ['Content-Type' => 'application/x-gzip'], + responseBody: 'Servas!', + ); + + $string = Http::getBodyString($response); + + set_error_handler($previousHandler); + + expect($warnings)->toBeEmpty() + ->and($string)->toBe('Servas!'); + }, +);