Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TASK] Adapt FAL dumpFile to use PSR-7 response objects
A new driver method streamFile() is added (specified in a new, internal StreamableDriverInterface). streamFile() returns a PSR-7 response which serves the contents of the file. Once this interface will be marked as public, third party drivers will be allowed to return an own response (e.g. containing a redirect to a CDN), providing full controls to headers. It also opens possibilties for optimizations like X-SendFile (apache) or X-Accell-Redirect (nginx) to be used by drivers. We also add SelfEmittableStreamInterface (marked as internal) to support the same fast file sending using readfile() – the interface provides a hook which is called by the AbstractApplication in sendResponse. That means that file contents do not need to be read into memory, stored into a stream, and then read again, but can be piped to stdout by php directly. For all existing drivers backward compatibility is provided by wrapping their dumpFileContents() method into a decorator stream which calls dumpFileContents *when* the response is sent. That means middlewares are able to prevent/stop/enhance the response, but the driver method dumpFileContents is still used – it's delayed until Application::sendResponse. The dumpFileContents method of the ResourceStorage class is now deprecated. ResourceStorage->streamFile() should be used instead. Change-Id: I64e707c1f8350e409ff2505b98531b92b2936e02 Releases: master Resolves: #83793 Reviewed-on: https://review.typo3.org/55585 Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Benni Mack <benni@typo3.org> Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Susanne Moog <susanne.moog@typo3.org> Tested-by: Susanne Moog <susanne.moog@typo3.org>
- Loading branch information
1 parent
b6564a0
commit dc00234
Showing
11 changed files
with
406 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
typo3/sysext/core/Classes/Http/FalDumpFileContentsDecoratorStream.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
namespace TYPO3\CMS\Core\Http; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use GuzzleHttp\Psr7\StreamDecoratorTrait; | ||
use Psr\Http\Message\StreamInterface; | ||
use TYPO3\CMS\Core\Resource\Driver\DriverInterface; | ||
|
||
/** | ||
* A lazy stream, that wraps the FAL dumpFileContents() method to send file contents | ||
* using emit(), as defined in SelfEmittableStreamInterface. | ||
* This call will fall back to the FAL getFileContents() method if the fastpath possibility | ||
* using SelfEmittableStreamInterface is not used. | ||
* | ||
* @internal | ||
*/ | ||
class FalDumpFileContentsDecoratorStream implements StreamInterface, SelfEmittableStreamInterface | ||
{ | ||
use StreamDecoratorTrait; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
protected $identifier; | ||
|
||
/** | ||
* @var DriverInterface | ||
*/ | ||
protected $driver; | ||
|
||
/** | ||
* @var int | ||
*/ | ||
protected $size; | ||
|
||
/** | ||
* @param string $identifier | ||
* @param DriverInterface $driver | ||
* @param int $size | ||
*/ | ||
public function __construct(string $identifier, DriverInterface $driver, int $size) | ||
{ | ||
$this->identifier = $identifier; | ||
$this->driver = $driver; | ||
$this->size = $size; | ||
} | ||
|
||
/** | ||
* Emit the response to stdout, as specified in SelfEmittableStreamInterface. | ||
* Offload to the driver method dumpFileContents. | ||
*/ | ||
public function emit() | ||
{ | ||
$this->driver->dumpFileContents($this->identifier); | ||
} | ||
|
||
/** | ||
* Creates a stream (on demand). This method is consumed by the guzzle StreamDecoratorTrait | ||
* and is used when this stream is used without the emit() fastpath. | ||
* | ||
* @return StreamInterface | ||
*/ | ||
protected function createStream(): StreamInterface | ||
{ | ||
$stream = new Stream('php://temp', 'rw'); | ||
$stream->write($this->driver->getFileContents($this->identifier)); | ||
return $stream; | ||
} | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function getSize(): int | ||
{ | ||
return $this->size; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function isWritable(): bool | ||
{ | ||
return false; | ||
} | ||
|
||
/** | ||
* @param string $string | ||
* @throws \RuntimeException on failure. | ||
*/ | ||
public function write($string) | ||
{ | ||
throw new \RuntimeException('Cannot write to a ' . self::class, 1538331852); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
typo3/sysext/core/Classes/Http/SelfEmittableLazyOpenStream.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
namespace TYPO3\CMS\Core\Http; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use GuzzleHttp\Psr7\LazyOpenStream; | ||
|
||
/** | ||
* This class implements a stream that can be used like a usual PSR-7 stream | ||
* but is additionally able to provide a file-serving fastpath using readfile(). | ||
* The file this stream refers to is opened on demand. | ||
* | ||
* @internal | ||
*/ | ||
class SelfEmittableLazyOpenStream extends LazyOpenStream implements SelfEmittableStreamInterface | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
protected $filename; | ||
|
||
/** | ||
* Constructor setting up the PHP resource | ||
* | ||
* @param string $filename | ||
*/ | ||
public function __construct($filename) | ||
{ | ||
parent::__construct($filename, 'r'); | ||
$this->filename = $filename; | ||
} | ||
|
||
/** | ||
* Output the contents of the file to the output buffer | ||
*/ | ||
public function emit() | ||
{ | ||
readfile($this->filename, false); | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function isWritable(): bool | ||
{ | ||
return false; | ||
} | ||
|
||
/** | ||
* @param string $string | ||
* @throws \RuntimeException on failure. | ||
*/ | ||
public function write($string) | ||
{ | ||
throw new \RuntimeException('Cannot write to a ' . self::class, 1538331833); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
typo3/sysext/core/Classes/Http/SelfEmittableStreamInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
namespace TYPO3\CMS\Core\Http; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use Psr\Http\Message\StreamInterface; | ||
|
||
/** | ||
* A PSR-7 stream which allows to be emitted on its own. | ||
* | ||
* @internal | ||
*/ | ||
interface SelfEmittableStreamInterface extends StreamInterface | ||
{ | ||
/** | ||
* Output the contents of the stream to the output buffer | ||
*/ | ||
public function emit(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
typo3/sysext/core/Classes/Resource/Driver/StreamableDriverInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
declare(strict_types = 1); | ||
|
||
namespace TYPO3\CMS\Core\Resource\Driver; | ||
|
||
/* | ||
* This file is part of the TYPO3 CMS project. | ||
* | ||
* It is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License, either version 2 | ||
* of the License, or any later version. | ||
* | ||
* For the full copyright and license information, please read the | ||
* LICENSE.txt file that was distributed with this source code. | ||
* | ||
* The TYPO3 project - inspiring people to share! | ||
*/ | ||
|
||
use Psr\Http\Message\ResponseInterface; | ||
|
||
/** | ||
* An interface FAL drivers have to implement to fulfil the needs | ||
* of streaming files using PSR-7 Response objects. | ||
* | ||
* @internal | ||
*/ | ||
interface StreamableDriverInterface | ||
{ | ||
/** | ||
* Streams a file using a PSR-7 Response object. | ||
* | ||
* @param string $identifier | ||
* @param array $properties | ||
* @return ResponseInterface | ||
*/ | ||
public function streamFile(string $identifier, array $properties): ResponseInterface; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.