From c11a8eb92ea2c9e983f58b7d3e3fd553e4c7ddc3 Mon Sep 17 00:00:00 2001 From: Shaun Simmons Date: Fri, 28 Jul 2017 16:30:25 -0400 Subject: [PATCH 1/2] Add a Monolog activation strategy for ignoring specific HTTP codes --- .../HttpCodeActivationStrategy.php | 62 ++++++++++++++++++ .../HttpCodeActivationStrategyTest.php | 65 +++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php create mode 100644 src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php diff --git a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php new file mode 100644 index 0000000000000..a8cc8a0f115c9 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Handler\FingersCrossed; + +use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpFoundation\RequestStack; + +/** + * Activation strategy that ignores certain HTTP codes. + * + * @author Shaun Simmons + */ +class HttpCodeActivationStrategy extends ErrorLevelActivationStrategy +{ + private $exclusions; + private $requestStack; + + public function __construct(RequestStack $requestStack, array $exclusions, $actionLevel) + { + parent::__construct($actionLevel); + + $this->requestStack = $requestStack; + $this->exclusions = $exclusions; + } + + public function isHandlerActivated(array $record) + { + $isActivated = parent::isHandlerActivated($record); + + if ( + $isActivated + && isset($record['context']['exception']) + && $record['context']['exception'] instanceof HttpException + && ($request = $this->requestStack->getMasterRequest()) + ) { + foreach ($this->exclusions as $exclusion) { + if ($record['context']['exception']->getStatusCode() !== $exclusion['code']) { + continue; + } + + $urlBlacklist = null; + if (count($exclusion['url'])) { + return !preg_match('{('.implode('|', $exclusion['url']).')}i', $request->getPathInfo()); + } + + return false; + } + } + + return $isActivated; + } +} diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php new file mode 100644 index 0000000000000..18ad0a2c3dca4 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Tests\Handler\FingersCrossed; + +use Monolog\Logger; +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Exception\HttpException; + +class HttpCodeActivationStrategyTest extends TestCase +{ + /** + * @dataProvider isActivatedProvider + */ + public function testIsActivated($url, $record, $expected) + { + $requestStack = new RequestStack(); + $requestStack->push(Request::create($url)); + + $strategy = new HttpCodeActivationStrategy( + $requestStack, + array( + array('code' => 403, 'url' => array()), + array('code' => 404, 'url' => array()), + array('code' => 405, 'url' => array()), + array('code' => 400, 'url' => array('^/400/a', '^/400/b')), + ), + Logger::WARNING + ); + + $this->assertEquals($expected, $strategy->isHandlerActivated($record)); + } + + public function isActivatedProvider() + { + return array( + array('/test', array('level' => Logger::ERROR), true), + array('/400', array('level' => Logger::ERROR, 'context' => $this->getContextException(400)), true), + array('/400/a', array('level' => Logger::ERROR, 'context' => $this->getContextException(400)), false), + array('/400/b', array('level' => Logger::ERROR, 'context' => $this->getContextException(400)), false), + array('/400/c', array('level' => Logger::ERROR, 'context' => $this->getContextException(400)), true), + array('/401', array('level' => Logger::ERROR, 'context' => $this->getContextException(401)), true), + array('/403', array('level' => Logger::ERROR, 'context' => $this->getContextException(403)), false), + array('/404', array('level' => Logger::ERROR, 'context' => $this->getContextException(404)), false), + array('/405', array('level' => Logger::ERROR, 'context' => $this->getContextException(405)), false), + array('/500', array('level' => Logger::ERROR, 'context' => $this->getContextException(500)), true), + ); + } + + protected function getContextException($code) + { + return array('exception' => new HttpException($code)); + } +} From 6fc1cc3ec3830aa1a1b2e078a81125fd52f957ef Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 4 Apr 2018 08:24:09 +0200 Subject: [PATCH 2/2] added some validation --- .../HttpCodeActivationStrategy.php | 16 +++++++++++-- .../HttpCodeActivationStrategyTest.php | 24 +++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php index a8cc8a0f115c9..561af6f3948b6 100644 --- a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php +++ b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/HttpCodeActivationStrategy.php @@ -25,8 +25,20 @@ class HttpCodeActivationStrategy extends ErrorLevelActivationStrategy private $exclusions; private $requestStack; + /** + * @param array $exclusions each exclusion must have a "code" and "urls" keys + */ public function __construct(RequestStack $requestStack, array $exclusions, $actionLevel) { + foreach ($exclusions as $exclusion) { + if (!array_key_exists('code', $exclusion)) { + throw new \LogicException(sprintf('An exclusion must have a "code" key')); + } + if (!array_key_exists('urls', $exclusion)) { + throw new \LogicException(sprintf('An exclusion must have a "urls" key')); + } + } + parent::__construct($actionLevel); $this->requestStack = $requestStack; @@ -49,8 +61,8 @@ public function isHandlerActivated(array $record) } $urlBlacklist = null; - if (count($exclusion['url'])) { - return !preg_match('{('.implode('|', $exclusion['url']).')}i', $request->getPathInfo()); + if (count($exclusion['urls'])) { + return !preg_match('{('.implode('|', $exclusion['urls']).')}i', $request->getPathInfo()); } return false; diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php index 18ad0a2c3dca4..9f0b0b3735e44 100644 --- a/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/Handler/FingersCrossed/HttpCodeActivationStrategyTest.php @@ -20,6 +20,22 @@ class HttpCodeActivationStrategyTest extends TestCase { + /** + * @expectedException \LogicException + */ + public function testExclusionsWithoutCode() + { + new HttpCodeActivationStrategy(new RequestStack(), array(array('urls' => array())), Logger::WARNING); + } + + /** + * @expectedException \LogicException + */ + public function testExclusionsWithoutUrls() + { + new HttpCodeActivationStrategy(new RequestStack(), array(array('code' => 404)), Logger::WARNING); + } + /** * @dataProvider isActivatedProvider */ @@ -31,10 +47,10 @@ public function testIsActivated($url, $record, $expected) $strategy = new HttpCodeActivationStrategy( $requestStack, array( - array('code' => 403, 'url' => array()), - array('code' => 404, 'url' => array()), - array('code' => 405, 'url' => array()), - array('code' => 400, 'url' => array('^/400/a', '^/400/b')), + array('code' => 403, 'urls' => array()), + array('code' => 404, 'urls' => array()), + array('code' => 405, 'urls' => array()), + array('code' => 400, 'urls' => array('^/400/a', '^/400/b')), ), Logger::WARNING );