Added debug mode to allow access to detailed error messages

This commit is contained in:
Chris Kankiewicz
2020-02-22 23:24:50 -07:00
parent 6d2d214c49
commit 1732a61c9e
9 changed files with 364 additions and 56 deletions

View File

@@ -1,3 +1,5 @@
DEBUG=false
DARK_MODE=false
DISPLAY_READMES=true

View File

@@ -3,6 +3,17 @@
use App\Support\Helpers;
return [
/**
* Enable application debugging and display error messages.
*
* !!! WARNING !!!
* It is recommended that debug remains OFF unless troubleshooting an issue.
* Leaving this enabled WILL cause leakage of sensitive server information.
*
* Default value: false
*/
'debug' => Helpers::env('DEBUG'),
/**
* Enable dark mode?
*

View File

@@ -2,11 +2,13 @@
namespace App\Bootstrap;
use App\Middlewares;
use App\Providers;
use DI\Bridge\Slim\Bridge;
use DI\Container;
use Invoker\CallableResolver;
use Middlewares;
use Middlewares as HttpMiddlewares;
use PHLAK\Config\Config;
use Slim\App;
use Tightenco\Collect\Support\Collection;
@@ -17,6 +19,12 @@ class AppManager
Providers\ConfigProvider::class,
Providers\FinderProvider::class,
Providers\TwigProvider::class,
Providers\WhoopsProvider::class,
];
/** @const Array of application middlewares */
protected const MIDDLEWARES = [
Middlewares\WhoopsMiddleware::class
];
/** @var Container The applicaiton container */
@@ -26,7 +34,7 @@ class AppManager
protected $callableResolver;
/**
* Create a new Provider object.
* Create a new AppManager object.
*
* @param \DI\Container $container
* @param \Invoker\CallableResolver $callableResolver
@@ -46,13 +54,16 @@ class AppManager
{
$this->registerProviders();
$app = Bridge::create($this->container);
$app->add(new Middlewares\Expires([
'application/zip' => '+1 hour',
'text/json' => '+1 hour',
]));
$this->registerMiddlewares($app);
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorMiddleware->setDefaultErrorHandler(ErrorHandler::class);
$this->container->call(function (App $app, Config $config): void {
if (! $config->get('app.debug', false)) {
return;
}
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorMiddleware->setDefaultErrorHandler(ErrorHandler::class);
});
return $app;
}
@@ -72,4 +83,25 @@ class AppManager
}
);
}
/**
* Register application middlewares.
*
* @param \Slim\App $app
*
* @return void
*/
protected function registerMiddlewares(App $app): void
{
Collection::make(self::MIDDLEWARES)->each(
function (string $middleware) use ($app): void {
$app->add($middleware);
}
);
$app->add(new HttpMiddlewares\Expires([
'application/zip' => '+1 hour',
'text/json' => '+1 hour',
]));
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace App\Middlewares;
use PHLAK\Config\Config;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\RunInterface;
class WhoopsMiddleware
{
/** @var RunInterface The Whoops component */
protected $whoops;
/** @var PrettyPageHandler The pretty page handler */
protected $pageHandler;
/** @var JsonResponseHandler The JSON response handler */
protected $jsonHandler;
/** @var Config The application config */
protected $config;
/**
* Create a new WhoopseMiddleware object.
*
* @param \Whoops\RunInterface $config
* @param \Whoops\Handler\PrettyPageHandler $pageHandler
* @param \Whoops\Handler\JsonResponseHandler $jsonHandler
* @param \PHLAK\Config\Config $config
*/
public function __construct(
RunInterface $whoops,
PrettyPageHandler $pageHandler,
JsonResponseHandler $jsonHandler,
Config $config
) {
$this->whoops = $whoops;
$this->pageHandler = $pageHandler;
$this->jsonHandler = $jsonHandler;
$this->config = $config;
}
/**
* Invoke the WhoopseMiddleware class.
*
* @param \Psr\Http\Message\ServerRequestInterface $request
* @param \Psr\Http\Server\RequestHandlerInterface $handler
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke(Request $request, RequestHandler $handler): ResponseInterface
{
$this->pageHandler->addDataTable('Application Config', $this->config->split('app')->toArray());
$this->pageHandler->setPageTitle(
sprintf('%s • Directory Lister', $this->pageHandler->getPageTitle())
);
$this->whoops->pushHandler($this->pageHandler);
if (in_array('application/json', explode(',', $request->getHeaderLine('Accept')))) {
$this->whoops->pushHandler($this->jsonHandler);
}
$this->whoops->register();
return $handler->handle($request);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Providers;
use DI\Container;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Run;
use Whoops\RunInterface;
class WhoopsProvider
{
/** @var Container The applicaiton container */
protected $container;
/**
* Create a new WhoopsProvider object.
*
* @param \DI\Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Initialize and register the Whoops component.
*
* @return void
*/
public function __invoke(): void
{
$this->container->set(PrettyPageHandler::class, new PrettyPageHandler);
$this->container->set(JsonResponseHandler::class, new JsonResponseHandler);
$this->container->set(RunInterface::class, new Run);
}
}

View File

@@ -13,6 +13,7 @@
"php": ">=7.2",
"ext-zip": "*",
"erusev/parsedown-extra": "^0.8.1",
"filp/whoops": "^2.7",
"middlewares/cache": "^2.0",
"phlak/config": "^6.1",
"php-di/php-di": "^6.0",

157
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "871b5d48a53bf07bdac340934b41325c",
"content-hash": "1a4f0a5fb5a91dc494cb5479886f6001",
"packages": [
{
"name": "erusev/parsedown",
@@ -151,6 +151,67 @@
],
"time": "2020-02-05T20:36:27+00:00"
},
{
"name": "filp/whoops",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130",
"reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130",
"shasum": ""
},
"require": {
"php": "^5.5.9 || ^7.0",
"psr/log": "^1.0.1"
},
"require-dev": {
"mockery/mockery": "^0.9 || ^1.0",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0",
"symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0"
},
"suggest": {
"symfony/var-dumper": "Pretty print complex values better with var-dumper available",
"whoops/soap": "Formats errors as SOAP responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.6-dev"
}
},
"autoload": {
"psr-4": {
"Whoops\\": "src/Whoops/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Filipe Dobreira",
"homepage": "https://github.com/filp",
"role": "Developer"
}
],
"description": "php error handling for cool kids",
"homepage": "https://filp.github.io/whoops/",
"keywords": [
"error",
"exception",
"handling",
"library",
"throwable",
"whoops"
],
"time": "2020-01-15T10:00:00+00:00"
},
{
"name": "jeremeamia/superclosure",
"version": "2.4.0",
@@ -1043,6 +1104,53 @@
],
"time": "2018-10-30T17:12:04+00:00"
},
{
"name": "psr/log",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2019-11-01T11:05:21+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
@@ -3765,53 +3873,6 @@
],
"time": "2019-01-08T18:20:26+00:00"
},
{
"name": "psr/log",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2019-11-01T11:05:21+00:00"
},
{
"name": "psy/psysh",
"version": "v0.9.12",

View File

@@ -3,7 +3,11 @@
namespace Tests\Bootstrap;
use App\Bootstrap\AppManager;
use App\Middlewares;
use App\Providers;
use DI\Container;
use Invoker\CallableResolver;
use Middlewares as HttpMiddlewares;
use Slim\App;
use Tests\TestCase;
@@ -16,4 +20,19 @@ class AppManangerTest extends TestCase
$this->assertInstanceOf(App::class, $app);
}
public function test_it_registeres_providers(): void
{
$callableResolver = $this->container->get(CallableResolver::class);
$container = $this->createMock(Container::class);
$container->expects($this->atLeast(4))->method('call')->withConsecutive(
[$callableResolver->resolve(Providers\ConfigProvider::class)],
[$callableResolver->resolve(Providers\FinderProvider::class)],
[$callableResolver->resolve(Providers\TwigProvider::class)],
[$callableResolver->resolve(Providers\WhoopsProvider::class)],
);
(new AppManager($container, $callableResolver))();
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Tests\Middlewares;
use App\Middlewares\WhoopsMiddleware;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Tests\TestCase;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\PrettyPageHandler;
use Whoops\RunInterface;
class WhoopsMiddlewareTest extends TestCase
{
public function test_it_registers_whoops_with_the_page_handler(): void
{
$pageHandler = $this->createMock(PrettyPageHandler::class);
$pageHandler->expects($this->once())->method('getPageTitle')->willReturn(
'Test title; please ignore'
);
$pageHandler->expects($this->once())->method('setPageTitle')->with(
'Test title; please ignore • Directory Lister'
);
$pageHandler->expects($this->once())->method('addDataTable')->with(
'Application Config', $this->config->split('app')->toArray()
);
$whoops = $this->createMock(RunInterface::class);
$whoops->expects($this->once())->method('pushHandler')->with(
$pageHandler
);
$middleware = new WhoopsMiddleware(
$whoops, $pageHandler, new JsonResponseHandler, $this->config
);
$middleware(
$this->createMock(ServerRequestInterface::class),
$this->createMock(RequestHandlerInterface::class)
);
}
public function test_it_registers_whoops_with_the_json_handler(): void
{
$pageHandler = $this->createMock(PrettyPageHandler::class);
$pageHandler->expects($this->once())->method('getPageTitle')->willReturn(
'Test title; please ignore'
);
$pageHandler->expects($this->once())->method('setPageTitle')->with(
'Test title; please ignore • Directory Lister'
);
$pageHandler->expects($this->once())->method('addDataTable')->with(
'Application Config', $this->config->split('app')->toArray()
);
$jsonHandler = new JsonResponseHandler;
$whoops = $this->createMock(RunInterface::class);
$whoops->expects($this->exactly(2))->method('pushHandler')->withConsecutive(
[$pageHandler],
[$jsonHandler]
);
$middleware = new WhoopsMiddleware(
$whoops, $pageHandler, $jsonHandler, $this->config
);
$request = $this->createMock(ServerRequestInterface::class);
$request->expects($this->once())->method('getHeaderLine')->willReturn('application/json');
$middleware($request, $this->createMock(RequestHandlerInterface::class));
}
}