middlewares / filesystem
Middleware to save or read responses using Flysystem
Installs: 21 096
Dependents: 4
Suggesters: 0
Security: 0
Stars: 9
Watchers: 2
Forks: 1
Open Issues: 0
Requires
- php: ^7.2 || ^8.0
- league/flysystem: ^1.0
- middlewares/utils: ^3.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.0
- laminas/laminas-diactoros: ^2.3
- oscarotero/php-cs-fixer-config: ^1.0
- phpstan/phpstan: ^0.12
- phpunit/phpunit: ^8|^9
- squizlabs/php_codesniffer: ^3.0
README
Middleware to save or read responses from files. It uses Flysystem as filesystem handler, so you can use not only a local directories, but also any other adapter like ftp, sftp, dropbox, etc... This package includes the following components:
Requirements
- PHP >= 7.2
- A PSR-7 http library
- A PSR-15 middleware dispatcher
Installation
This package is installable and autoloadable via Composer as middlewares/filesystem.
composer require middlewares/filesystem
Example
Dispatcher::run([ Middlewares\Reader::createFromDirectory(__DIR__.'/assets') ]);
Reader
To read the response body from a file under the following conditions:
- Only
GET
methods are allowed, returning a405
code otherwise. - If the request path has no extension, assume it's a directory and append
/index.html
. For example: if the request path is/post/23
, the file used is/post/23/index.html
. - It can handle gzipped files. For example, if
/post/23/index.html
does not exists but/post/23/index.html.gz
is available and the request headerAccept-Encoding
containsgzip
, returns it. Accept-Ranges
is also supported, useful to server big files like videos.
Example using a ftp storage:
use League\Flysystem\Filesystem; use League\Flysystem\Adapter\Ftp; $filesystem = new Filesystem(new Ftp([ 'host' => 'ftp.example.com', 'username' => 'username', 'password' => 'password', 'port' => 21, 'root' => '/path/to/root', 'passive' => true, 'ssl' => true, 'timeout' => 30, ])); Dispatcher::run([ new Middlewares\Reader($filesystem) ]);
Optionally, you can provide a Psr\Http\Message\ResponseFactoryInterface
and Psr\Http\Message\StreamFactoryInterface
, that will be used to create the response and stream. If they are not not defined, Middleware\Utils\Factory will be used to detect them automatically.
$responseFactory = new MyOwnResponseFactory(); $streamFactory = new MyOwnStreamFactory(); $reader = new Middlewares\Reader($filesystem, $responseFactory, $streamFactory);
continueOnError
Allows to continue to the next middleware on error (file not found, method not allowed, etc). This allows to create a simple caching system as the following:
$cache = new Flysystem(new Local(__DIR__.'/path/to/files')); Dispatcher::run([ (new Middlewares\Reader($cache)) //read and returns the cached response... ->continueOnError(), //...but continue if the file does not exists new Middlewares\Writer($cache), //save the response in the cache new Middlewares\AuraRouter($route), //create a response using, for example, Aura.Router ]);
Writer
Saves the response content into a file if all of the following conditions are met:
- The method is
GET
- The status code is
200
- The
Cache-Control
header does not containno-cache
andno-store
To be compatible with Reader
behaviour:
- If the request path has no extension, assume it's a directory and append
/index.html
. For example: if the request path is/post/23
, the file saved is/post/23/index.html
. - If the response is gzipped (has the header
Content-Encoding: gzip
) the file is saved with the extension .gz. For example/post/23/index.html.gz
(instead/post/23/index.html
).
$filesystem = new Flysystem(new Local(__DIR__.'/storage')); Dispatcher::run([ new Middlewares\Writer($filesystem) ]);
Optionally, you can provide a Psr\Http\Message\StreamFactoryInterface
as the second that will be used to create a new body to the response. If it's not defined, Middleware\Utils\Factory will be used to detect it automatically.
$streamFactory = new MyOwnStreamFactory(); $reader = new Middlewares\Writer($filesystem, $streamFactory);
Helpers
createFromDirectory
Both Reader
and Writer
have a static method as a shortcut to create instances using a directory in the local filesystem, due this is the most common case:
Dispatcher::run([ Middlewares\Writer::createFromDirectory(__DIR__.'/assets') Middlewares\Reader::createFromDirectory(__DIR__.'/assets') ]);
Please see CHANGELOG for more information about recent changes and CONTRIBUTING for contributing details.
The MIT License (MIT). Please see LICENSE for more information.