From 0e26e06ef9860f4d93bf01513c4fea150f52e209 Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Mon, 11 Aug 2025 18:20:23 -0300 Subject: [PATCH 1/7] Enable request support to gzip. Add support to request to parse gzip encoded posts. --- framework/web/Request.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/framework/web/Request.php b/framework/web/Request.php index 7b9645d532d..3cc27e5cd8c 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -307,6 +307,8 @@ class Request extends \yii\base\Request * @var HeaderCollection Collection of request headers. */ private $_headers; + /** @var boolean Enable gzip inflate */ + public $gzip = true; /** @@ -569,7 +571,15 @@ public function getIsFlash() public function getRawBody() { if ($this->_rawBody === null) { - $this->_rawBody = file_get_contents('php://input'); + $contentEncoding = $this->headers->get('Content-Encoding', ''); + if (!empty($contentEncoding)) { + $contentEncoding = strtolower($contentEncoding); + } + if ($this->gzip && $contentEncoding === 'gzip' || $contentEncoding === 'deflate') { + $this->_rawBody = gzinflate(file_get_contents('php://input')); + } else { + $this->_rawBody = file_get_contents('php://input'); + } } return $this->_rawBody; From 82a167296d3f1af362a073f8c51290f24c7dab66 Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 10:21:02 -0300 Subject: [PATCH 2/7] Cleanup code. --- framework/web/Request.php | 15 ++++++--------- tests/framework/web/RequestTest.php | 8 +++++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/framework/web/Request.php b/framework/web/Request.php index 3cc27e5cd8c..bd992e4eceb 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -571,17 +571,14 @@ public function getIsFlash() public function getRawBody() { if ($this->_rawBody === null) { - $contentEncoding = $this->headers->get('Content-Encoding', ''); - if (!empty($contentEncoding)) { - $contentEncoding = strtolower($contentEncoding); - } - if ($this->gzip && $contentEncoding === 'gzip' || $contentEncoding === 'deflate') { - $this->_rawBody = gzinflate(file_get_contents('php://input')); - } else { - $this->_rawBody = file_get_contents('php://input'); + $this->_rawBody = file_get_contents('php://input'); + if ($this->gzip) { + $contentEncoding = $this->headers->get('Content-Encoding', ''); + if ($contentEncoding === 'gzip' || $contentEncoding === 'deflate' || $contentEncoding === 'x-gzip') { + $this->_rawBody = gzinflate($this->_rawBody); + } } } - return $this->_rawBody; } diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index 932392e187d..18a64ee1c40 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -564,7 +564,7 @@ public function testGetScriptUrlWithEmptyServer() $_SERVER = []; $this->expectException(\yii\base\InvalidConfigException::class); - + $request->getScriptUrl(); } @@ -1410,4 +1410,10 @@ public function testForwardedNotTrusted() $this->assertSame('10.0.0.1', $request->userIP, 'User IP fail!'); $this->assertSame('http://yiiframework.com', $request->hostInfo, 'Host info fail!'); } + + + public function testGetRawBody() + { + $request = new Request(['gzip' => true]); + } } From f0652cf42130ed10b3142e5ff56a0421d5d8e21e Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 10:25:56 -0300 Subject: [PATCH 3/7] Add empty tests. --- tests/framework/web/RequestTest.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index 18a64ee1c40..0d7683573d6 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -1412,8 +1412,18 @@ public function testForwardedNotTrusted() } - public function testGetRawBody() + public function testGzipGetRawBody() { $request = new Request(['gzip' => true]); + $request->headers->add('Content-encoding', 'gzip'); + $this->assertSame($request->getRawBody(), null); + + $request = new Request(['gzip' => true]); + $request->headers->add('Content-encoding', 'deflate'); + $this->assertSame($request->getRawBody(), null); + + $request = new Request(['gzip' => true]); + $request->headers->add('Content-encoding', 'x-gzip'); + $this->assertSame($request->getRawBody(), null); } } From 9bb1411c3ba752a68233bd572fec5a03769da471 Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 11:34:04 -0300 Subject: [PATCH 4/7] Add tests and better support to different compression post body algorithms. --- framework/web/Request.php | 27 ++++++++++++++----- tests/framework/web/RequestTest.php | 40 +++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/framework/web/Request.php b/framework/web/Request.php index bd992e4eceb..29e73fd3b36 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -307,7 +307,7 @@ class Request extends \yii\base\Request * @var HeaderCollection Collection of request headers. */ private $_headers; - /** @var boolean Enable gzip inflate */ + /** @var boolean Enable automatically inflate post requests with gzip/deflate Content-Encoding headers */ public $gzip = true; @@ -564,6 +564,24 @@ public function getIsFlash() private $_rawBody; + /** + * Inflate the raw body on needed. + * @return void + */ + private function tryInflateRawBody() + { + if ($this->gzip) { + $contentEncoding = $this->headers->get('Content-Encoding', '', true); + if ($contentEncoding === 'gzip' || $contentEncoding === 'x-gzip') { + // gzip (RFC 1952) + $this->_rawBody = gzdecode($this->_rawBody); + } elseif ($contentEncoding === 'deflate') { + // raw deflate (RFC 1951) + $this->_rawBody = gzinflate($this->_rawBody); + } + } + } + /** * Returns the raw HTTP request body. * @return string the request body @@ -572,12 +590,7 @@ public function getRawBody() { if ($this->_rawBody === null) { $this->_rawBody = file_get_contents('php://input'); - if ($this->gzip) { - $contentEncoding = $this->headers->get('Content-Encoding', ''); - if ($contentEncoding === 'gzip' || $contentEncoding === 'deflate' || $contentEncoding === 'x-gzip') { - $this->_rawBody = gzinflate($this->_rawBody); - } - } + $this->tryInflateRawBody(); } return $this->_rawBody; } diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index 0d7683573d6..dd4a1e4cc90 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -7,6 +7,7 @@ namespace yiiunit\framework\web; +use ReflectionClass; use yii\web\Request; use yiiunit\TestCase; @@ -1411,19 +1412,38 @@ public function testForwardedNotTrusted() $this->assertSame('http://yiiframework.com', $request->hostInfo, 'Host info fail!'); } - public function testGzipGetRawBody() { $request = new Request(['gzip' => true]); - $request->headers->add('Content-encoding', 'gzip'); - $this->assertSame($request->getRawBody(), null); - - $request = new Request(['gzip' => true]); - $request->headers->add('Content-encoding', 'deflate'); - $this->assertSame($request->getRawBody(), null); - + $reflection = new ReflectionClass($request); + $tryInflateRawBody = $reflection->getMethod('tryInflateRawBody'); + $rawBody = $reflection->getProperty('_rawBody'); + $rawBody->setAccessible(true); + $tryInflateRawBody->setAccessible(true); + + $testString = 'hello!'; + // Test gzip as described in RFC 1950, Content-Encoding: gzip or x-gzip + $request->headers->add('Content-encoding','gzip'); + $rawBody->setValue($request, gzencode($testString)); + $tryInflateRawBody->invoke($request); + $this->assertSame($testString, $rawBody->getValue($request), 'Could not deflate correctly'); + $request->headers->add('Content-encoding','x-gzip'); + $rawBody->setValue($request, gzencode($testString)); + $tryInflateRawBody->invoke($request); + $this->assertSame($testString, $rawBody->getValue($request), 'Could not deflate correctly'); + + // Test deflate as described in RFC 1951, Content-Encoding: deflate $request = new Request(['gzip' => true]); - $request->headers->add('Content-encoding', 'x-gzip'); - $this->assertSame($request->getRawBody(), null); + $request->headers->add('Content-encoding','deflate'); + $rawBody->setValue($request, gzdeflate($testString)); + $tryInflateRawBody->invoke($request); + $this->assertSame($testString, $rawBody->getValue($request), 'Could not deflate correctly'); + + // Test backwards compatibility + $request = new Request(['gzip' => false]); + $request->headers->add('Content-encoding','deflate'); + $rawBody->setValue($request, gzdeflate($testString)); + $tryInflateRawBody->invoke($request); + $this->assertSame(gzdeflate($testString), $rawBody->getValue($request), 'Gzip flag not working as expected'); } } From 03726850467ba0f3371d76d6a068f3588f133091 Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 11:40:31 -0300 Subject: [PATCH 5/7] Make gzip decompression disabled by default. --- framework/web/Request.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/web/Request.php b/framework/web/Request.php index 29e73fd3b36..c228c5f851b 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -308,7 +308,7 @@ class Request extends \yii\base\Request */ private $_headers; /** @var boolean Enable automatically inflate post requests with gzip/deflate Content-Encoding headers */ - public $gzip = true; + public $gzip = false; /** From a9b47af7950708437d02c4d53c95eaf84b2d809d Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 11:41:55 -0300 Subject: [PATCH 6/7] Add one more test that tests if gzip decompression is really disabled by default. --- tests/framework/web/RequestTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/framework/web/RequestTest.php b/tests/framework/web/RequestTest.php index dd4a1e4cc90..0ab27a02376 100644 --- a/tests/framework/web/RequestTest.php +++ b/tests/framework/web/RequestTest.php @@ -1445,5 +1445,11 @@ public function testGzipGetRawBody() $rawBody->setValue($request, gzdeflate($testString)); $tryInflateRawBody->invoke($request); $this->assertSame(gzdeflate($testString), $rawBody->getValue($request), 'Gzip flag not working as expected'); + + $request = new Request(); + $request->headers->add('Content-encoding','deflate'); + $rawBody->setValue($request, gzdeflate($testString)); + $tryInflateRawBody->invoke($request); + $this->assertSame(gzdeflate($testString), $rawBody->getValue($request), 'Gzip flag not working as expected'); } } From aa2235ee3baaa48bc3ae01e20a282ad3bd099a32 Mon Sep 17 00:00:00 2001 From: Lucas Alves Date: Tue, 12 Aug 2025 12:01:20 -0300 Subject: [PATCH 7/7] Add CHANGELOG description --- framework/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 3435d9a60a4..672054c0001 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -12,6 +12,7 @@ Yii Framework 2 Change Log - Bug #20453: Fix PHPStan/Psalm types in `yii\web\View` (max-s-lab) - Enh #20461: Add PHPStan/Psalm annotations for `yii\filters\auth\AuthInterface` (max-s-lab) - Bug #20459: Fix return type in `RequestParserInterface::parse` (max-s-lab) +- Enh #20477: Added Content-Encoding(aka gzip) support to request body (lucaswitch) 2.0.53 June 27, 2025