Skip to content

Disable and enable debug bar #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 26, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ $app->run($request, $response);

You don't need to copy any static assets from phpdebugbar vendor!

### How to force disable or enable PHP Debug Bar?

Sometimes you want to have control when show or not PHP Debug Bar:
* custom content negotiation,
* allow to make redirects.

We allow you to disable attaching phpdebugbar using `X-Debug-Bar: false` header, cookie or request attribute.
To force enable just send request with `X-Debug-Bar` header, cookie or request attribute with `true` value.

### How to install on Zend Expressive?

You need to register ConfigProvider and pipe provided middleware:
Expand Down
13 changes: 12 additions & 1 deletion src/PhpDebugBarMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
*/
final class PhpDebugBarMiddleware implements MiddlewareInterface
{
const FORCE_KEY = 'X-Debug-Bar';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it public const

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better naming: X-Disable-Debug-Bar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this case should name X-Enable-Debug-Bar

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

const FORCE_HEADER = self::FORCE_KEY;
const FORCE_COOKIE = self::FORCE_KEY;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really useful, because it repeats the same thing, so we can reuse the same thing, too

const FORCE_ATTRIBUTE = self::FORCE_KEY;

protected $debugBarRenderer;

public function __construct(DebugBarRenderer $debugbarRenderer)
Expand All @@ -41,7 +46,13 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface

$response = $handler->handle($request);

if (!$this->isHtmlAccepted($request)) {
$forceHeaderValue = $request->getHeaderLine(self::FORCE_HEADER);
$forceCookieValue = $request->getCookieParams()[self::FORCE_COOKIE] ?? '';
$forceAttibuteValue = $request->getAttribute(self::FORCE_ATTRIBUTE, '');
$isForceEnable = in_array('true', [$forceHeaderValue, $forceCookieValue, $forceAttibuteValue], true);
$isForceDisable = in_array('false', [$forceHeaderValue, $forceCookieValue, $forceAttibuteValue], true);

if ($isForceDisable || (!$isForceEnable && !$this->isHtmlAccepted($request))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem is, some middlewares will just return 302 response (redirect somewhere), and are unaware of the debug bar middleware present. So we need to check for 302 at least additionally.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about other redirects? https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections

You have right - redirect is possible, but sometimes you want to debug request / response before redirection - this PR allow to do that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's by using ForceEnable - cool. Problem is, when a middleware redirects, it's not smart enough to know that this debug bar is present and therefore will probably not set ForceDisable header.

return $response;
}

Expand Down
98 changes: 89 additions & 9 deletions test/PhpDebugBarMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ class PhpDebugBarMiddlewareTest extends TestCase
protected function setUp()
{
$this->debugbarRenderer = $this->getMockBuilder(JavascriptRenderer::class)->disableOriginalConstructor()->getMock();
$this->debugbarRenderer->method('renderHead')->willReturn('RenderHead');
$this->debugbarRenderer->method('render')->willReturn('RenderBody');

$this->middleware = new PhpDebugBarMiddleware($this->debugbarRenderer);
}

public function testTwoPassCallingForCompatibility(): void
{
$request = new ServerRequest();
$response = new Response();
$response->getBody()->write('ResponseBody');
$calledOut = false;
$outFunction = function ($request, $response) use (&$calledOut) {
$calledOut = true;
Expand All @@ -40,21 +44,62 @@ public function testTwoPassCallingForCompatibility(): void
$result = call_user_func($this->middleware, $request, $response, $outFunction);

$this->assertTrue($calledOut, 'Out is not called');
$this->assertSame('ResponseBody', (string) $result->getBody());
$this->assertSame($response, $result);
}

public function testNotAttachIfNotAccept(): void
{
$request = new ServerRequest();
$response = new Response();
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
$this->assertSame('ResponseBody', (string) $result->getBody());
$this->assertSame($response, $result);
}

public function testForceAttachDebugbarIfHeaderPresents(): void
{
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'application/json', 'X-Debug-Bar' => 'true']);
$response = new Response();
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertSame("<html><head>RenderHead</head><body><h1>DebugBar</h1><p>Response:</p><pre>HTTP/1.1 200 OK\r\n\r\nResponseBody</pre>RenderBody</body></html>", (string) $result->getBody());
}

public function testForceAttachDebugbarIfCookiePresents(): void
{
$cookies = ['X-Debug-Bar' => 'true'];
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'application/json'], $cookies);
$response = new Response();
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertSame("<html><head>RenderHead</head><body><h1>DebugBar</h1><p>Response:</p><pre>HTTP/1.1 200 OK\r\n\r\nResponseBody</pre>RenderBody</body></html>", (string) $result->getBody());
}

public function testForceAttachDebugbarIfAttributePresents(): void
{
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'application/json']);
$request = $request->withAttribute('X-Debug-Bar', 'true');
$response = new Response();
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertSame("<html><head>RenderHead</head><body><h1>DebugBar</h1><p>Response:</p><pre>HTTP/1.1 200 OK\r\n\r\nResponseBody</pre>RenderBody</body></html>", (string) $result->getBody());
}

public function testAttachToNoneHtmlResponse(): void
{
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']);
Expand All @@ -63,9 +108,6 @@ public function testAttachToNoneHtmlResponse(): void

$requestHandler = new RequestHandlerStub($response);

$this->debugbarRenderer->expects($this->once())->method('renderHead')->willReturn('RenderHead');
$this->debugbarRenderer->expects($this->once())->method('render')->willReturn('RenderBody');

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
Expand All @@ -80,26 +122,64 @@ public function testAttachToHtmlResponse(): void
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$this->debugbarRenderer->expects($this->once())->method('renderHead')->willReturn('RenderHead');
$this->debugbarRenderer->expects($this->once())->method('render')->willReturn('RenderBody');

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
$this->assertSame($response, $result);
$this->assertSame("ResponseBodyRenderHeadRenderBody", (string) $result->getBody());
}

public function testForceNotAttachDebugbarIfHeaderPresents(): void
{
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html', 'X-Debug-Bar' => 'false']);
$response = new Response('php://memory', 200, ['Content-Type' => 'text/html']);
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
$this->assertSame($response, $result);
$this->assertSame("ResponseBody", (string) $result->getBody());
}

public function testForceNotAttachDebugbarIfCookiePresents(): void
{
$cookie = ['X-Debug-Bar' => 'false'];
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html'], $cookie);
$response = new Response('php://memory', 200, ['Content-Type' => 'text/html']);
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
$this->assertSame($response, $result);
$this->assertSame("ResponseBody", (string) $result->getBody());
}

public function testForceNotAttachDebugbarIfAttributePresents(): void
{
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']);
$request = $request->withAttribute('X-Debug-Bar', 'false');
$response = new Response('php://memory', 200, ['Content-Type' => 'text/html']);
$response->getBody()->write('ResponseBody');
$requestHandler = new RequestHandlerStub($response);

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
$this->assertSame($response, $result);
$this->assertSame("ResponseBody", (string) $result->getBody());
}

public function testAppendsToEndOfHtmlResponse(): void
{
$html = '<html><head><title>Foo</title></head><body>Content</body>';
$request = new ServerRequest([], [], null, null, 'php://input', ['Accept' => 'text/html']);
$response = new Response\HtmlResponse($html);
$requestHandler = new RequestHandlerStub($response);

$this->debugbarRenderer->expects($this->once())->method('renderHead')->willReturn('RenderHead');
$this->debugbarRenderer->expects($this->once())->method('render')->willReturn('RenderBody');

$result = $this->middleware->process($request, $requestHandler);

$this->assertTrue($requestHandler->isCalled(), 'Request handler is not called');
Expand Down