From 24100296b777aa4733666c4162e972db390275a7 Mon Sep 17 00:00:00 2001 From: "M. Yilmaz SUSLU" Date: Tue, 24 May 2016 01:38:46 +0300 Subject: [PATCH 1/2] Handle redirect responses before serializing the response body --- src/PhpDebugBarMiddleware.php | 47 ++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/PhpDebugBarMiddleware.php b/src/PhpDebugBarMiddleware.php index e774dcb..ef530f8 100644 --- a/src/PhpDebugBarMiddleware.php +++ b/src/PhpDebugBarMiddleware.php @@ -9,6 +9,7 @@ use Psr\Http\Message\UriInterface; use Zend\Diactoros\Response; use Zend\Diactoros\Response\HtmlResponse; +use Zend\Diactoros\Response\RedirectResponse; use Zend\Diactoros\Response\Serializer; use Zend\Diactoros\Stream; @@ -34,8 +35,8 @@ public function __construct(DebugBarRenderer $debugbarRenderer) /** * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @param callable $next + * @param ResponseInterface $response + * @param callable $next * * @return ResponseInterface */ @@ -47,7 +48,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res $outResponse = $next($request, $response); - if (!$this->isHtmlAccepted($request)) { + if (!$this->isHtmlAccepted($request) || $this->isRedirectResponse($outResponse)) { return $outResponse; } @@ -64,10 +65,10 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res return $outResponse; } - $outResponseBody = Serializer::toString($outResponse); - $template = '%s

DebugBar

Response:

%s
%s'; + $outResponseBody = Serializer::toString($outResponse); + $template = '%s

DebugBar

Response:

%s
%s'; $escapedOutResponseBody = htmlspecialchars($outResponseBody); - $result = sprintf($template, $debugBarHead, $escapedOutResponseBody, $debugBarBody); + $result = sprintf($template, $debugBarHead, $escapedOutResponseBody, $debugBarBody); return new HtmlResponse($result); } @@ -91,9 +92,9 @@ private function getStaticFile(UriInterface $uri) return; } - $stream = new Stream($fullPathToFile, 'r'); + $stream = new Stream($fullPathToFile, 'r'); $staticResponse = new Response($stream); - $contentType = $this->getContentTypeByFileName($fullPathToFile); + $contentType = $this->getContentTypeByFileName($fullPathToFile); return $staticResponse->withHeader('Content-type', $contentType); } @@ -108,13 +109,13 @@ 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', + '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', ]; @@ -147,8 +148,8 @@ private function isHtmlAccepted(ServerRequestInterface $request) /** * @param MessageInterface $message - * @param string $headerName - * @param string $value + * @param string $headerName + * @param string $value * * @return bool */ @@ -156,4 +157,16 @@ private function hasHeaderContains(MessageInterface $message, $headerName, $valu { return strpos($message->getHeaderLine($headerName), $value) !== false; } + + /** + * Returns a boolean TRUE for if the response is a redirect. + * + * @param MessageInterface $message + * + * @return bool + */ + private function isRedirectResponse(ResponseInterface $response) + { + return $response instanceof RedirectResponse; + } } From 4317e1c869d913a75b82c68dda5d22c5738d6398 Mon Sep 17 00:00:00 2001 From: "M. Yilmaz SUSLU" Date: Tue, 24 May 2016 23:57:44 +0300 Subject: [PATCH 2/2] Check HTTP status code for redirects instead of instance, add unit tests --- src/PhpDebugBarMiddleware.php | 14 ++++-- test/PhpDebugBarMiddlewareTest.php | 74 ++++++++++++++++++++++-------- 2 files changed, 65 insertions(+), 23 deletions(-) diff --git a/src/PhpDebugBarMiddleware.php b/src/PhpDebugBarMiddleware.php index ef530f8..166f42c 100644 --- a/src/PhpDebugBarMiddleware.php +++ b/src/PhpDebugBarMiddleware.php @@ -9,7 +9,6 @@ use Psr\Http\Message\UriInterface; use Zend\Diactoros\Response; use Zend\Diactoros\Response\HtmlResponse; -use Zend\Diactoros\Response\RedirectResponse; use Zend\Diactoros\Response\Serializer; use Zend\Diactoros\Stream; @@ -48,7 +47,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res $outResponse = $next($request, $response); - if (!$this->isHtmlAccepted($request) || $this->isRedirectResponse($outResponse)) { + if (!$this->isHtmlAccepted($request) || $this->isRedirect($outResponse)) { return $outResponse; } @@ -159,14 +158,19 @@ private function hasHeaderContains(MessageInterface $message, $headerName, $valu } /** - * Returns a boolean TRUE for if the response is a redirect. + * Returns a boolean TRUE for if the response has redirect status code. + * + * Five common HTTP status codes indicates a redirection beginning from 301. + * 304 not modified and 305 use proxy are not redirects. + * + * @see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection * * @param MessageInterface $message * * @return bool */ - private function isRedirectResponse(ResponseInterface $response) + private function isRedirect(ResponseInterface $response) { - return $response instanceof RedirectResponse; + return in_array($response->getStatusCode(), [301, 302, 303, 307, 308]); } } diff --git a/test/PhpDebugBarMiddlewareTest.php b/test/PhpDebugBarMiddlewareTest.php index f474d81..ac6f0cc 100644 --- a/test/PhpDebugBarMiddlewareTest.php +++ b/test/PhpDebugBarMiddlewareTest.php @@ -23,16 +23,17 @@ class PhpDebugBarMiddlewareTest extends PHPUnit_Framework_TestCase protected function setUp() { $this->debugbarRenderer = $this->getMockBuilder(JavascriptRenderer::class)->disableOriginalConstructor()->getMock(); - $this->middleware = new PhpDebugBarMiddleware($this->debugbarRenderer); + $this->middleware = new PhpDebugBarMiddleware($this->debugbarRenderer); } public function testNotAttachIfNotAccept() { - $request = new ServerRequest(); - $response = new Response(); - $calledOut = false; + $request = new ServerRequest(); + $response = new Response(); + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -44,12 +45,13 @@ public function testNotAttachIfNotAccept() public function testAttachToNoneHtmlResponse() { - $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); + $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); $response = new Response(); $response->getBody()->write('ResponseBody'); - $calledOut = false; + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -65,12 +67,13 @@ public function testAttachToNoneHtmlResponse() public function testAttachToHtmlResponse() { - $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); + $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); $response = new Response('php://memory', 200, ['Content-Type' => 'text/html']); $response->getBody()->write('ResponseBody'); - $calledOut = false; + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -86,12 +89,13 @@ public function testAttachToHtmlResponse() public function testAppendsToEndOfHtmlResponse() { - $html = 'FooContent'; - $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); - $response = new Response\HtmlResponse($html); - $calledOut = false; + $html = 'FooContent'; + $request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']); + $response = new Response\HtmlResponse($html); + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -109,13 +113,14 @@ 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'); + $uri = new Uri('http://example.com/phpdebugbar/boo.css'); + $request = new ServerRequest([], [], $uri, null, 'php://memory'); $response = new Response\HtmlResponse(''); - $calledOut = false; + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -134,15 +139,16 @@ public function testHandleStaticFile($extension, $contentType) $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'); + $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; + $calledOut = false; $outFunction = function ($request, $response) use (&$calledOut) { $calledOut = true; + return $response; }; @@ -153,6 +159,38 @@ public function testHandleStaticFile($extension, $contentType) $this->assertSame('filecontent', (string) $result->getBody()); } + /** + * @dataProvider statusCodeProvider + */ + public function testHandleRedirects($code, $handle) + { + $request = new ServerRequest(); + $response = new Response('php://memory', $code, ['Location' => 'http://www.foo.bar']); + $calledOut = false; + $outFunction = function ($request, $response) use (&$calledOut) { + $calledOut = true; + + return $response; + }; + + $result = call_user_func($this->middleware, $request, $response, $outFunction); + + $this->assertEquals($response->getStatusCode() === $code, $handle); + $this->assertTrue($calledOut, 'Out is not called'); + $this->assertSame($response, $result); + } + + public function statusCodeProvider() + { + return [ + [301, true], + [302, true], + [303, true], + [307, true], + [308, true], + ]; + } + public function getContentTypes() { return [