Skip to content

Commit

Permalink
Merge pull request #10 from harikt/fix-issue-1
Browse files Browse the repository at this point in the history
Added CallbackStream so large files can be served.
  • Loading branch information
harikt committed Feb 17, 2017
2 parents 5412d41 + 5f7dbf5 commit 1cfa157
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* `AssetLocator` class added to add / manipulate asset names and location
* Exception `PathNotFound` added.
* Added phpunit as require-dev dependency.
* Added CallbackStream which is copied from https://github.com/zendframework/zend-diactoros/blob/83e8d98b9915de76c659ce27d683c02a0f99fa90/src/CallbackStream.php
* Added https://github.com/http-interop/http-factory, so can work with any psr-7 implementations.

## BC BREAK

Expand Down
14 changes: 10 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@
"require": {
"php":"^5.6 || ^7.0",
"psr/http-message":"^1.0",
"zendframework/zend-diactoros":"^1.0"
"http-interop/http-factory":"^0.2"
},
"require-dev": {
"phpunit/phpunit": "5.7",
"http-interop/http-factory-diactoros":"^0.2"
},
"suggest": {
"http-interop/http-factory-diactoros": "Use zend framework zend-diactoros as the psr7 implementaion",
"http-interop/http-factory-slim": "Use slim http as the psr7 implementaion",
"http-interop/http-factory-guzzle": "Use guzzlehttp as the psr7 implementaion"
},
"autoload": {
"psr-4": {
Expand All @@ -27,8 +36,5 @@
"psr-4": {
"Hkt\\Psr7Asset\\":"tests/src/"
}
},
"require-dev": {
"phpunit/phpunit": "5.7"
}
}
2 changes: 1 addition & 1 deletion src/AssetAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res

$asset = $this->domain->getAsset($vendor, $package, $file);
$this->responder->setData(array('asset' => $asset));
return $this->responder->__invoke($response);
return $this->responder->__invoke();
}

if ($next) {
Expand Down
36 changes: 20 additions & 16 deletions src/AssetResponder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
namespace Hkt\Psr7Asset;

use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\CallbackStream;
use SplFileObject;

/**
Expand All @@ -21,14 +20,22 @@ class AssetResponder
*/
protected $data;

/**
*
* @var Interop\Http\Factory\ResponseFactoryInterface
*
*/
protected $responseFactory;

/**
*
* Constructor.
*
*/
public function __construct()
public function __construct($responseFactory)
{
$this->data = (object) array();
$this->responseFactory = $responseFactory;
}

/**
Expand Down Expand Up @@ -60,19 +67,17 @@ public function getData()

/**
*
* Modifies and returns the response.
*
* @param ResponseInterface $response
* Returns the response.
*
* @return ResponseInterface $response
*
*/
public function __invoke(ResponseInterface $response)
public function __invoke()
{
if ($this->isValidAsset()) {
return $this->ok($response);
return $this->ok();
}
return $this->notFound($response);
return $this->notFound();
}

/**
Expand All @@ -90,11 +95,9 @@ protected function isValidAsset()
/**
* Sets a 200 OK response with the asset contents.
*
* @param ResponseInterface $response
*
* @return ResponseInterface
*/
protected function ok(ResponseInterface $response)
protected function ok()
{
$path = $this->data->asset->path;
$callable = function () use ($path) {
Expand All @@ -105,8 +108,10 @@ protected function ok(ResponseInterface $response)

return '';
};

$response = $this->responseFactory->createResponse(200);

return $response
->withStatus(200)
->withBody(new CallbackStream($callable))
->withHeader('Content-Length', (string) filesize($this->data->asset->path))
->withHeader('Content-Type', $this->data->asset->type)
Expand All @@ -116,13 +121,12 @@ protected function ok(ResponseInterface $response)
/**
* Sets a 404 Not Found response.
*
* @param ResponseInterface $response
*
* @return ResponseInterface
*/
protected function notFound(ResponseInterface $response)
protected function notFound()
{
$response = $this->responseFactory->createResponse(404);
$response->getBody()->write("Not found");
return $response->withStatus(404);
return $response;
}
}
185 changes: 185 additions & 0 deletions src/CallbackStream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @see http://github.com/zendframework/zend-diactoros for the canonical source repository
* @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
*
* This class is copied from https://github.com/zendframework/zend-diactoros
* so that other psr-7 implementations can use the package without installing
* zendframework/zend-diactoros
*/

namespace Hkt\Psr7Asset;

use InvalidArgumentException;
use RuntimeException;
use Psr\Http\Message\StreamInterface;

/**
* Implementation of PSR HTTP streams
*/
class CallbackStream implements StreamInterface
{
/**
* @var callable|null
*/
protected $callback;

/**
* @param callable $callback
* @throws InvalidArgumentException
*/
public function __construct(callable $callback)
{
$this->attach($callback);
}

/**
* {@inheritdoc}
*/
public function __toString()
{
return $this->getContents();
}

/**
* {@inheritdoc}
*/
public function close()
{
$this->callback = null;
}

/**
* {@inheritdoc}
*/
public function detach()
{
$callback = $this->callback;
$this->callback = null;
return $callback;
}

/**
* Attach a new callback to the instance.
*
* @param callable $callback
* @throws InvalidArgumentException for callable callback
*/
public function attach(callable $callback)
{
$this->callback = $callback;
}

/**
* {@inheritdoc}
*/
public function getSize()
{
}

/**
* {@inheritdoc}
*/
public function tell()
{
throw new RuntimeException('Callback streams cannot tell position');
}

/**
* {@inheritdoc}
*/
public function eof()
{
return empty($this->callback);
}

/**
* {@inheritdoc}
*/
public function isSeekable()
{
return false;
}

/**
* {@inheritdoc}
*/
public function seek($offset, $whence = SEEK_SET)
{
throw new RuntimeException('Callback streams cannot seek position');
}

/**
* {@inheritdoc}
*/
public function rewind()
{
throw new RuntimeException('Callback streams cannot rewind position');
}

/**
* {@inheritdoc}
*/
public function isWritable()
{
return false;
}

/**
* {@inheritdoc}
*/
public function write($string)
{
throw new RuntimeException('Callback streams cannot write');
}

/**
* {@inheritdoc}
*/
public function isReadable()
{
return false;
}

/**
* {@inheritdoc}
*/
public function read($length)
{
throw new RuntimeException('Callback streams cannot read');
}

/**
* {@inheritdoc}
*/
public function getContents()
{
$callback = $this->detach();
return $callback ? $callback() : '';
}

/**
* {@inheritdoc}
*/
public function getMetadata($key = null)
{
$metadata = [
'eof' => $this->eof(),
'stream_type' => 'callback',
'seekable' => false
];

if (null === $key) {
return $metadata;
}

if (! array_key_exists($key, $metadata)) {
return null;
}

return $metadata[$key];
}
}
5 changes: 4 additions & 1 deletion tests/src/AssetActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory;
use Http\Factory\Diactoros\ResponseFactory;

class AssetActionTest extends \PHPUnit_Framework_TestCase
{
Expand All @@ -24,7 +25,9 @@ public function setUp()

$service = new AssetService($locator);

$this->responder = new AssetResponder();
$responseFactory = new ResponseFactory();

$this->responder = new AssetResponder($responseFactory);

$this->action = new AssetAction($service, $this->responder);
}
Expand Down
5 changes: 3 additions & 2 deletions tests/src/AssetResponderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
use Http\Factory\Diactoros\ResponseFactory;

class AssetResponderTest extends \PHPUnit_Framework_TestCase
{
Expand All @@ -13,8 +14,8 @@ class AssetResponderTest extends \PHPUnit_Framework_TestCase
public function setUp()
{
$this->asset_dir = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'web';

$this->responder = new AssetResponder();
$responseFactory = new ResponseFactory();
$this->responder = new AssetResponder($responseFactory);
}

public function test__invoke_Ok()
Expand Down

0 comments on commit 1cfa157

Please sign in to comment.