diff --git a/composer.json b/composer.json index 5204335..ebad855 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "zendframework/zend-diactoros": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.6" + "phpunit/phpunit": "^4.8.6", + "mikey179/vfsStream": "^1.6" }, "autoload": { "psr-4": { diff --git a/src/PhpDebugBarMiddleware.php b/src/PhpDebugBarMiddleware.php index c05232f..e774dcb 100644 --- a/src/PhpDebugBarMiddleware.php +++ b/src/PhpDebugBarMiddleware.php @@ -6,8 +6,11 @@ use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\UriInterface; +use Zend\Diactoros\Response; use Zend\Diactoros\Response\HtmlResponse; use Zend\Diactoros\Response\Serializer; +use Zend\Diactoros\Stream; /** * PhpDebugBarMiddleware @@ -38,6 +41,10 @@ public function __construct(DebugBarRenderer $debugbarRenderer) */ public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next) { + if ($staticFile = $this->getStaticFile($request->getUri())) { + return $staticFile; + } + $outResponse = $next($request, $response); if (!$this->isHtmlAccepted($request)) { @@ -65,6 +72,59 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res return new HtmlResponse($result); } + /** + * @param UriInterface $uri + * + * @return ResponseInterface|null + */ + private function getStaticFile(UriInterface $uri) + { + if (strpos($uri->getPath(), $this->debugBarRenderer->getBaseUrl()) !== 0) { + return; + } + + $pathToFile = substr($uri->getPath(), strlen($this->debugBarRenderer->getBaseUrl())); + + $fullPathToFile = $this->debugBarRenderer->getBasePath() . $pathToFile; + + if (!file_exists($fullPathToFile)) { + return; + } + + $stream = new Stream($fullPathToFile, 'r'); + $staticResponse = new Response($stream); + $contentType = $this->getContentTypeByFileName($fullPathToFile); + + return $staticResponse->withHeader('Content-type', $contentType); + } + + /** + * @param string $filename + * + * @return string + */ + private function getContentTypeByFileName($filename) + { + $ext = pathinfo($filename, PATHINFO_EXTENSION); + + $map = [ + 'css' => 'text/css', + 'js' => 'text/javascript', + 'otf' => 'font/opentype', + 'eot' => 'application/vnd.ms-fontobject', + 'svg' => 'image/svg+xml', + 'ttf' => 'application/font-sfnt', + 'woff' => 'application/font-woff', + 'woff2' => 'application/font-woff2', + ]; + + if (isset($map[$ext])) { + return $map[$ext]; + } + + return 'text/plain'; + } + /** * @param ResponseInterface $response * diff --git a/test/PhpDebugBarMiddlewareTest.php b/test/PhpDebugBarMiddlewareTest.php index 1f6766c..f474d81 100644 --- a/test/PhpDebugBarMiddlewareTest.php +++ b/test/PhpDebugBarMiddlewareTest.php @@ -3,16 +3,19 @@ namespace PhpMiddlewareTest\PhpDebugBar; use DebugBar\JavascriptRenderer; +use org\bovigo\vfs\vfsStream; use PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware; +use PHPUnit_Framework_TestCase; use Zend\Diactoros\Response; use Zend\Diactoros\ServerRequest; +use Zend\Diactoros\Uri; /** * PhpDebugBarMiddlewareTest * * @author Witold Wasiczko */ -class PhpDebugBarMiddlewareTest extends \PHPUnit_Framework_TestCase +class PhpDebugBarMiddlewareTest extends PHPUnit_Framework_TestCase { protected $debugbarRenderer; protected $middleware; @@ -101,4 +104,61 @@ public function testAppendsToEndOfHtmlResponse() $this->assertSame($response, $result); $this->assertSame($html . 'RenderHeadRenderBody', (string) $result->getBody()); } + + public function testTryToHandleNotExistingStaticFile() + { + $this->debugbarRenderer->expects($this->any())->method('getBaseUrl')->willReturn('/phpdebugbar'); + + $uri = new Uri('http://example.com/phpdebugbar/boo.css'); + $request = new ServerRequest([], [], $uri, null, 'php://memory'); + $response = new Response\HtmlResponse(''); + + $calledOut = false; + $outFunction = function ($request, $response) use (&$calledOut) { + $calledOut = true; + return $response; + }; + + $result = call_user_func($this->middleware, $request, $response, $outFunction); + $this->assertTrue($calledOut, 'Out is not called'); + $this->assertSame($response, $result); + } + + /** + * @dataProvider getContentTypes + */ + public function testHandleStaticFile($extension, $contentType) + { + $root = vfsStream::setup('boo'); + + $this->debugbarRenderer->expects($this->any())->method('getBaseUrl')->willReturn('/phpdebugbar'); + $this->debugbarRenderer->expects($this->any())->method('getBasePath')->willReturn(vfsStream::url('boo')); + + $uri = new Uri(sprintf('http://example.com/phpdebugbar/debugbar.%s', $extension)); + $request = new ServerRequest([], [], $uri, null, 'php://memory'); + $response = new Response\HtmlResponse(''); + + vfsStream::newFile(sprintf('debugbar.%s', $extension))->withContent('filecontent')->at($root); + + $calledOut = false; + $outFunction = function ($request, $response) use (&$calledOut) { + $calledOut = true; + return $response; + }; + + $result = call_user_func($this->middleware, $request, $response, $outFunction); + $this->assertFalse($calledOut, 'Out is called'); + $this->assertNotSame($response, $result); + $this->assertSame($contentType, $result->getHeaderLine('Content-type')); + $this->assertSame('filecontent', (string) $result->getBody()); + } + + public function getContentTypes() + { + return [ + ['css', 'text/css'], + ['js', 'text/javascript'], + ['html', 'text/plain'], + ]; + } }