Custom render exception, and set request throttle to .env
This commit is contained in:
parent
8a60842646
commit
2554cbeda2
4 changed files with 121 additions and 7 deletions
|
|
@ -1,3 +1,5 @@
|
|||
displayError=true
|
||||
logErrors=true
|
||||
logErrorDetails=true
|
||||
RequestLimit=1
|
||||
RequestLimitTimeout=10000
|
||||
|
|
|
|||
108
app/ErrorHandler/CustomHtmlErrorRenderer.php
Normal file
108
app/ErrorHandler/CustomHtmlErrorRenderer.php
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Slim Framework (https://slimframework.com)
|
||||
*
|
||||
* @license https://github.com/slimphp/Slim/blob/4.x/LICENSE.md (MIT License)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\ErrorHandler;
|
||||
|
||||
use Slim\Error\AbstractErrorRenderer;
|
||||
use Throwable;
|
||||
|
||||
use function get_class;
|
||||
use function htmlentities;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Default Slim application HTML Error Renderer
|
||||
*/
|
||||
class CustomHtmlErrorRenderer extends AbstractErrorRenderer
|
||||
{
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
* @param bool $displayErrorDetails
|
||||
* @return string
|
||||
*/
|
||||
public function __invoke(Throwable $exception, bool $displayErrorDetails): string
|
||||
{
|
||||
if ($displayErrorDetails) {
|
||||
$html = '<p>The application could not run because of the following error:</p>';
|
||||
$html .= '<h2>Details</h2>';
|
||||
$html .= $this->renderExceptionFragment($exception);
|
||||
} else {
|
||||
$html = "<p><b>{$exception->getMessage()}</b><br>{$this->getErrorDescription($exception)}</p>";
|
||||
}
|
||||
|
||||
return $this->renderHtmlBody($this->getErrorTitle($exception), $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
* @return string
|
||||
*/
|
||||
private function renderExceptionFragment(Throwable $exception): string
|
||||
{
|
||||
$html = sprintf('<div><strong>Type:</strong> %s</div>', get_class($exception));
|
||||
|
||||
$code = $exception->getCode();
|
||||
if ($code !== null) {
|
||||
$html .= sprintf('<div><strong>Code:</strong> %s</div>', $code);
|
||||
}
|
||||
|
||||
$message = $exception->getMessage();
|
||||
if ($message !== null) {
|
||||
$html .= sprintf('<div><strong>Message:</strong> %s</div>', htmlentities($message));
|
||||
}
|
||||
|
||||
$file = $exception->getFile();
|
||||
if ($file !== null) {
|
||||
$html .= sprintf('<div><strong>File:</strong> %s</div>', $file);
|
||||
}
|
||||
|
||||
$line = $exception->getLine();
|
||||
if ($line !== null) {
|
||||
$html .= sprintf('<div><strong>Line:</strong> %s</div>', $line);
|
||||
}
|
||||
|
||||
$trace = $exception->getTraceAsString();
|
||||
if ($trace !== null) {
|
||||
$html .= '<h2>Trace</h2>';
|
||||
$html .= sprintf('<pre>%s</pre>', htmlentities($trace));
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
* @param string $html
|
||||
* @return string
|
||||
*/
|
||||
public function renderHtmlBody(string $title = '', string $html = ''): string
|
||||
{
|
||||
return sprintf(
|
||||
'<html>' .
|
||||
' <head>' .
|
||||
" <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" .
|
||||
' <title>%s</title>' .
|
||||
' <style>' .
|
||||
' body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif}' .
|
||||
' h1{margin:0;font-size:48px;font-weight:normal;line-height:48px}' .
|
||||
' strong{display:inline-block;width:65px}' .
|
||||
' </style>' .
|
||||
' </head>' .
|
||||
' <body>' .
|
||||
' <h1>%s</h1>' .
|
||||
' <div>%s</div>' .
|
||||
' </body>' .
|
||||
'</html>',
|
||||
$title,
|
||||
$title,
|
||||
$html
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use App\ErrorHandler\CustomHtmlErrorRenderer;
|
||||
use App\Middlewares\ThrottleMiddleware;
|
||||
use Dotenv\Dotenv;
|
||||
use Dotenv\Exception\InvalidPathException;
|
||||
|
|
@ -51,6 +52,8 @@ class Kernel
|
|||
env('logErrors', false),
|
||||
env('logErrorDetails', false)
|
||||
);
|
||||
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
|
||||
$errorHandler->registerErrorRenderer('text/html', CustomHtmlErrorRenderer::class);
|
||||
}
|
||||
|
||||
private static function loadEnv()
|
||||
|
|
@ -69,7 +72,7 @@ class Kernel
|
|||
|
||||
public static function env(string $key, $default = null)
|
||||
{
|
||||
$value = getenv($key);
|
||||
$value = self::$env[$key] ?? $default;
|
||||
|
||||
if ($value === false) {
|
||||
return $default;
|
||||
|
|
@ -93,10 +96,6 @@ class Kernel
|
|||
return;
|
||||
}
|
||||
|
||||
// if (Str::startsWith($value, '"') && Str::endsWith($value, '"')) {
|
||||
// return substr($value, 1, -1);
|
||||
// }
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Middlewares;
|
|||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Slim\Exception\HttpForbiddenException;
|
||||
use Stiphle\Throttle\LeakyBucket;
|
||||
|
||||
class ThrottleMiddleware
|
||||
|
|
@ -23,8 +24,12 @@ class ThrottleMiddleware
|
|||
//! Enable APC in Laragon https://forum.laragon.org/topic/1245/regarding-caching-plugin-availability/4
|
||||
$storage = new \Stiphle\Storage\Apcu();
|
||||
$throttle->setStorage($storage);
|
||||
// limit to 1 per second
|
||||
$throttle->throttle('api.request', 1, 10000);
|
||||
// limit to 1 per second by default
|
||||
$estimate = $throttle->getEstimate('api.request', env('RequestLimit', 1), env('RequestLimitTimeout', 1000));
|
||||
if ($estimate > 1000) {
|
||||
throw new HttpForbiddenException($request, 'Too many requests');
|
||||
}
|
||||
$throttle->throttle('api.request', env('RequestLimit', 1), env('RequestLimitTimeout', 1000));
|
||||
return $handler->handle($request);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue