From 0c74ea48cca5b04e4b8521c3ace7ec657d808541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rube=CC=81n=20Robles?= Date: Wed, 14 Feb 2024 18:08:57 +0100 Subject: [PATCH] ignore compression on file, stream or whenever Content-Encoding header is present --- src/ResponseCompression.php | 11 +++++---- tests/ResponseCompressionTest.php | 38 ++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/ResponseCompression.php b/src/ResponseCompression.php index c98b920..6c10c35 100644 --- a/src/ResponseCompression.php +++ b/src/ResponseCompression.php @@ -3,6 +3,8 @@ namespace OpenSoutheners\LaravelVaporResponseCompression; use Closure; +use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\StreamedResponse; class ResponseCompression { @@ -10,7 +12,6 @@ class ResponseCompression * Handle an incoming request. * * @param \Illuminate\Http\Request $request - * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) @@ -40,12 +41,14 @@ public function handle($request, Closure $next) /** * Determine if response should be compressed. * - * @param \Illuminate\Http\Response $response - * @return bool + * @param \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response $response */ protected function shouldCompressResponse($response): bool { - return config('response-compression.enable', true) + return ! $response instanceof BinaryFileResponse + && ! $response instanceof StreamedResponse + && ! $response->headers->has('Content-Encoding') + && config('response-compression.enable', true) && strlen($response->getContent()) >= config('response-compression.threshold', 10000); } diff --git a/tests/ResponseCompressionTest.php b/tests/ResponseCompressionTest.php index d9a8604..24a98b9 100644 --- a/tests/ResponseCompressionTest.php +++ b/tests/ResponseCompressionTest.php @@ -42,7 +42,7 @@ public function testClientGetRawResponseWhenThresholdNotReached() ['content' => $this->lightResponseContent] ); } - + public function testClientGetRawResponseWhenNotEnabled() { config(['response-compression.enable' => false]); @@ -95,6 +95,42 @@ public function testClientGetResponseAskingAnUnrecognisedEncodingReceivesRawResp ); } + public function testClientGetResponseWithContentEncodingHeaderAlreadyAttachedReceivesRawResponse() + { + Route::get('/heavy-ignored', function () { + return response()->json([ + 'content' => $this->heavyResponseContent, + ], 200, ['Content-Encoding' => CompressionEncoding::DEFLATE]); + })->middleware(ResponseCompression::class); + + $response = $this->get('/heavy-ignored', ['Accept-Encoding' => CompressionEncoding::GZIP]); + + $response->assertHeader('Content-Encoding', CompressionEncoding::DEFLATE); + + $this->assertEquals( + $response->json(), + ['content' => $this->heavyResponseContent] + ); + } + + public function testClientGetStreamDownloadResponseReceivesRawResponse() + { + Route::get('/download', function () { + return response()->streamDownload(function () { + echo $this->heavyResponseContent; + }); + })->middleware(ResponseCompression::class); + + $response = $this->get('/download', ['Accept-Encoding' => CompressionEncoding::DEFLATE]); + + $response->assertHeaderMissing('Content-Encoding'); + + $this->assertEquals( + $response->streamedContent(), + $this->heavyResponseContent + ); + } + // TODO: vdechenaux/brotli is not compatible with Laravel dependencies... // public function testClientGetResponseUsingBrotliEncoding() // {