diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 5e5e8db36e233..adfe0a440737f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 7.3 --- + * Display profiler URL in logs + * Add `profiler.php` and `wdt.php` routing configuration files (use them instead of their XML equivalent) Before: diff --git a/src/Symfony/Bundle/WebProfilerBundle/EventListener/ProfilerLinkLogListener.php b/src/Symfony/Bundle/WebProfilerBundle/EventListener/ProfilerLinkLogListener.php new file mode 100644 index 0000000000000..b18a61c781a3d --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/EventListener/ProfilerLinkLogListener.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\WebProfilerBundle\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Psr\Log\LoggerInterface; + +/** + * @author Jérémy Romey jeremyFreeAgent + */ +final class ProfilerLinkLogListener implements EventSubscriberInterface +{ + public function __construct( + private ?LoggerInterface $logger = null, + private ?UrlGeneratorInterface $urlGenerator = null, + ) { + } + + public function onKernelResponse(ResponseEvent $event): void + { + if (null === $this->logger) { + return; + } + if (null === $this->urlGenerator) { + return; + } + + $response = $event->getResponse(); + $request = $event->getRequest(); + + if (!$event->isMainRequest()) { + return; + } + + if (!$response->headers->has('X-Debug-Token')) { + return; + } + + $this->logger->debug(\sprintf('See profiler at %s', $this->urlGenerator->generate('_profiler', ['token' => $response->headers->get('X-Debug-Token')], UrlGeneratorInterface::ABSOLUTE_URL))); + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::RESPONSE => ['onKernelResponse', -2048], + ]; + } +} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.php b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.php index edb464158045f..6079803e4232e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.php @@ -16,6 +16,7 @@ use Symfony\Bundle\WebProfilerBundle\Controller\RouterController; use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler; use Symfony\Bundle\WebProfilerBundle\Csp\NonceGenerator; +use Symfony\Bundle\WebProfilerBundle\EventListener\ProfilerLinkLogListener; use Symfony\Bundle\WebProfilerBundle\Profiler\CodeExtension; use Symfony\Bundle\WebProfilerBundle\Twig\WebProfilerExtension; use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; @@ -84,5 +85,14 @@ ->set('twig.extension.code', CodeExtension::class) ->args([service('debug.file_link_formatter'), param('kernel.project_dir'), param('kernel.charset')]) ->tag('twig.extension') + + ->set('web_profiler.profiler_link_log_listener', ProfilerLinkLogListener::class) + ->args([ + service('logger')->nullOnInvalid(), + service('router')->ignoreOnInvalid(), + ]) + + ->tag('monolog.logger', ['channel' => 'profiler']) + ->tag('kernel.event_subscriber') ; }; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/ProfilerLinkLogListenerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/ProfilerLinkLogListenerTest.php new file mode 100644 index 0000000000000..e8342b7109b54 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/ProfilerLinkLogListenerTest.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\WebProfilerBundle\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\WebProfilerBundle\EventListener\ProfilerLinkLogListener; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Psr\Log\LoggerInterface; + +/** + * @author Jérémy Romey jeremyFreeAgent + */ +final class ProfilerLinkLogListenerTest extends TestCase +{ + public function testProfilerLinkLog() + { + $response = new Response('I love Symfony', 200); + $response->headers->set('Location', 'https://example.com/'); + $response->headers->set('X-Debug-Token', '04bb3f'); + + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $logger = $this->createMock(LoggerInterface::class); + $logger + ->expects($this->once()) + ->method('debug') + ->with('See profiler at http://mydomain.com/_profiler/04bb3f') + ; + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator + ->expects($this->once()) + ->method('generate') + ->with('_profiler', ['token' => '04bb3f'], UrlGeneratorInterface::ABSOLUTE_URL) + ->willReturn('http://mydomain.com/_profiler/04bb3f') + ; + + $listener = new ProfilerLinkLogListener($logger, $urlGenerator); + $listener->onKernelResponse($event); + } + + public function testProfilerLinkLogShouldNotLogWhenNoLogger() + { + $response = new Response('I love Symfony', 200); + $response->headers->set('Location', 'https://example.com/'); + $response->headers->set('X-Debug-Token', '04bb3f'); + + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $logger = null; + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator + ->expects($this->never()) + ->method('generate') + ; + + $listener = new ProfilerLinkLogListener($logger, $urlGenerator); + $listener->onKernelResponse($event); + } + + public function testProfilerLinkLogShouldNotLogWhenNoUrlGenerator() + { + $response = new Response('I love Symfony', 200); + $response->headers->set('Location', 'https://example.com/'); + $response->headers->set('X-Debug-Token', '04bb3f'); + + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $logger = $this->createMock(LoggerInterface::class); + $logger + ->expects($this->never()) + ->method('debug') + ; + + $urlGenerator = null; + + $listener = new ProfilerLinkLogListener($logger, $urlGenerator); + $listener->onKernelResponse($event); + } + + public function testProfilerLinkLogShouldNotLogWhenNotMainRequest() + { + $response = new Response('I love Symfony', 200); + $response->headers->set('Location', 'https://example.com/'); + $response->headers->set('X-Debug-Token', '04bb3f'); + + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::SUB_REQUEST, $response); + + $logger = $this->createMock(LoggerInterface::class); + $logger + ->expects($this->never()) + ->method('debug') + ; + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator + ->expects($this->never()) + ->method('generate') + ; + + $listener = new ProfilerLinkLogListener($logger, $urlGenerator); + $listener->onKernelResponse($event); + } + + public function testProfilerLinkLogShouldNotLogWhenNoToken() + { + $response = new Response('I love Symfony', 200); + $response->headers->set('Location', 'https://example.com/'); + + $event = new ResponseEvent($this->createMock(Kernel::class), new Request(), HttpKernelInterface::MAIN_REQUEST, $response); + + $logger = $this->createMock(LoggerInterface::class); + $logger + ->expects($this->never()) + ->method('debug') + ; + + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $urlGenerator + ->expects($this->never()) + ->method('generate') + ; + + $listener = new ProfilerLinkLogListener($logger, $urlGenerator); + $listener->onKernelResponse($event); + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy