Browse Source
Add AppFramework GZip middleware to gzip responses
Add AppFramework GZip middleware to gzip responses
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>pull/20270/head
No known key found for this signature in database
GPG Key ID: F941078878347C0C
5 changed files with 256 additions and 0 deletions
-
1lib/composer/composer/autoload_classmap.php
-
1lib/composer/composer/autoload_static.php
-
5lib/private/AppFramework/DependencyInjection/DIContainer.php
-
86lib/private/AppFramework/Middleware/CompressionMiddleware.php
-
163tests/lib/AppFramework/Middleware/CompressionMiddlewareTest.php
@ -0,0 +1,86 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl> |
|||
* |
|||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\AppFramework\Middleware; |
|||
|
|||
use OC\AppFramework\OCS\BaseResponse; |
|||
use OCP\AppFramework\Http; |
|||
use OCP\AppFramework\Http\JSONResponse; |
|||
use OCP\AppFramework\Http\Response; |
|||
use OCP\AppFramework\Middleware; |
|||
use OCP\IRequest; |
|||
|
|||
class CompressionMiddleware extends Middleware { |
|||
|
|||
/** @var bool */ |
|||
private $useGZip; |
|||
|
|||
/** @var IRequest */ |
|||
private $request; |
|||
|
|||
public function __construct(IRequest $request) { |
|||
$this->request = $request; |
|||
$this->useGZip = false; |
|||
} |
|||
|
|||
public function afterController($controller, $methodName, Response $response) { |
|||
// By default we do not gzip
|
|||
$allowGzip = false; |
|||
|
|||
// Only return gzipped content for 200 responses
|
|||
if ($response->getStatus() !== Http::STATUS_OK) { |
|||
return $response; |
|||
} |
|||
|
|||
// Check if we are even asked for gzip
|
|||
$header = $this->request->getHeader('Accept-Encoding'); |
|||
if (strpos($header, 'gzip') === false) { |
|||
return $response; |
|||
} |
|||
|
|||
// We only allow gzip in some cases
|
|||
if ($response instanceof BaseResponse) { |
|||
$allowGzip = true; |
|||
} |
|||
if ($response instanceof JSONResponse) { |
|||
$allowGzip = true; |
|||
} |
|||
|
|||
if ($allowGzip) { |
|||
$this->useGZip = true; |
|||
$response->addHeader('Content-Encoding', 'gzip'); |
|||
} |
|||
|
|||
return $response; |
|||
} |
|||
|
|||
public function beforeOutput($controller, $methodName, $output) { |
|||
if (!$this->useGZip) { |
|||
return $output; |
|||
} |
|||
|
|||
return gzencode($output); |
|||
} |
|||
} |
|||
@ -0,0 +1,163 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
/** |
|||
* @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl> |
|||
* |
|||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace Test\AppFramework\Middleware; |
|||
|
|||
use OC\AppFramework\Middleware\CompressionMiddleware; |
|||
use OC\AppFramework\OCS\V1Response; |
|||
use OC\AppFramework\OCS\V2Response; |
|||
use OCP\AppFramework\Controller; |
|||
use OCP\AppFramework\Http; |
|||
use OCP\AppFramework\Http\DataResponse; |
|||
use OCP\AppFramework\Http\JSONResponse; |
|||
use OCP\IRequest; |
|||
|
|||
class CompressionMiddlewareTest extends \Test\TestCase { |
|||
|
|||
/** @var IRequest */ |
|||
private $request; |
|||
/** @var Controller */ |
|||
private $controller; |
|||
/** @var CompressionMiddleware */ |
|||
private $middleWare; |
|||
|
|||
protected function setUp(): void { |
|||
parent::setUp(); |
|||
|
|||
$this->request = $this->createMock(IRequest::class); |
|||
$this->middleWare = new CompressionMiddleware( |
|||
$this->request |
|||
); |
|||
|
|||
$this->controller = $this->createMock(Controller::class); |
|||
} |
|||
|
|||
public function testGzipOCSV1() { |
|||
$this->request->method('getHeader') |
|||
->with('Accept-Encoding') |
|||
->willReturn('gzip'); |
|||
|
|||
$response = $this->createMock(V1Response::class); |
|||
$response->expects($this->once()) |
|||
->method('addHeader') |
|||
->with('Content-Encoding', 'gzip'); |
|||
|
|||
$response->method('getStatus') |
|||
->willReturn(Http::STATUS_OK); |
|||
|
|||
$this->middleWare->beforeController($this->controller, 'myMethod'); |
|||
$this->middleWare->afterController($this->controller,'myMethod', $response); |
|||
|
|||
$output = 'myoutput'; |
|||
$result = $this->middleWare->beforeOutput($this->controller, 'myMethod', $output); |
|||
|
|||
$this->assertSame($output, gzdecode($result)); |
|||
} |
|||
|
|||
public function testGzipOCSV2() { |
|||
$this->request->method('getHeader') |
|||
->with('Accept-Encoding') |
|||
->willReturn('gzip'); |
|||
|
|||
$response = $this->createMock(V2Response::class); |
|||
$response->expects($this->once()) |
|||
->method('addHeader') |
|||
->with('Content-Encoding', 'gzip'); |
|||
|
|||
$response->method('getStatus') |
|||
->willReturn(Http::STATUS_OK); |
|||
|
|||
$this->middleWare->beforeController($this->controller, 'myMethod'); |
|||
$this->middleWare->afterController($this->controller,'myMethod', $response); |
|||
|
|||
$output = 'myoutput'; |
|||
$result = $this->middleWare->beforeOutput($this->controller, 'myMethod', $output); |
|||
|
|||
$this->assertSame($output, gzdecode($result)); |
|||
} |
|||
|
|||
public function testGzipJSONResponse() { |
|||
$this->request->method('getHeader') |
|||
->with('Accept-Encoding') |
|||
->willReturn('gzip'); |
|||
|
|||
$response = $this->createMock(JSONResponse::class); |
|||
$response->expects($this->once()) |
|||
->method('addHeader') |
|||
->with('Content-Encoding', 'gzip'); |
|||
|
|||
$response->method('getStatus') |
|||
->willReturn(Http::STATUS_OK); |
|||
|
|||
$this->middleWare->beforeController($this->controller, 'myMethod'); |
|||
$this->middleWare->afterController($this->controller,'myMethod', $response); |
|||
|
|||
$output = 'myoutput'; |
|||
$result = $this->middleWare->beforeOutput($this->controller, 'myMethod', $output); |
|||
|
|||
$this->assertSame($output, gzdecode($result)); |
|||
} |
|||
|
|||
public function testNoGzipDataResponse() { |
|||
$this->request->method('getHeader') |
|||
->with('Accept-Encoding') |
|||
->willReturn('gzip'); |
|||
|
|||
$response = $this->createMock(DataResponse::class); |
|||
$response->expects($this->never()) |
|||
->method('addHeader'); |
|||
|
|||
$response->method('getStatus') |
|||
->willReturn(Http::STATUS_OK); |
|||
$this->middleWare->beforeController($this->controller, 'myMethod'); |
|||
$this->middleWare->afterController($this->controller,'myMethod', $response); |
|||
|
|||
$output = 'myoutput'; |
|||
$result = $this->middleWare->beforeOutput($this->controller, 'myMethod', $output); |
|||
|
|||
$this->assertSame($output, $result); |
|||
} |
|||
|
|||
public function testNoGzipNo200() { |
|||
$this->request->method('getHeader') |
|||
->with('Accept-Encoding') |
|||
->willReturn('gzip'); |
|||
|
|||
$response = $this->createMock(JSONResponse::class); |
|||
$response->expects($this->never()) |
|||
->method('addHeader'); |
|||
|
|||
$response->method('getStatus') |
|||
->willReturn(Http::STATUS_NOT_FOUND); |
|||
|
|||
$this->middleWare->beforeController($this->controller, 'myMethod'); |
|||
$this->middleWare->afterController($this->controller,'myMethod', $response); |
|||
|
|||
$output = 'myoutput'; |
|||
$result = $this->middleWare->beforeOutput($this->controller, 'myMethod', $output); |
|||
|
|||
$this->assertSame($output, $result); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue