[HttpKernel] Prevent search engines from indexing dev applications

This commit is contained in:
Gary PEGEOT 2019-02-20 22:09:05 +00:00 committed by Fabien Potencier
parent 1ad6f6f319
commit 3dd86719bf
8 changed files with 134 additions and 0 deletions

View File

@ -108,6 +108,7 @@ class Configuration implements ConfigurationInterface
$this->addWebLinkSection($rootNode);
$this->addLockSection($rootNode);
$this->addMessengerSection($rootNode);
$this->addRobotsIndexSection($rootNode);
return $treeBuilder;
}
@ -1156,4 +1157,17 @@ class Configuration implements ConfigurationInterface
->end()
;
}
private function addRobotsIndexSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->booleanNode('disallow_search_engine_index')
->info('Enabled by default when debug is enabled.')
->defaultValue($this->debug)
->treatNullLike($this->debug)
->end()
->end()
;
}
}

View File

@ -394,6 +394,10 @@ class FrameworkExtension extends Extension
// remove tagged iterator argument for resource checkers
$container->getDefinition('config_cache_factory')->setArguments([]);
}
if (!$config['disallow_search_engine_index'] ?? false) {
$container->removeDefinition('disallow_search_engine_index_response_listener');
}
}
/**

View File

@ -85,5 +85,8 @@
<argument type="service" id="controller_name_converter" />
<tag name="kernel.event_subscriber" />
</service>
<service id="disallow_search_engine_index_response_listener" class="Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener">
<tag name="kernel.event_subscriber" />
</service>
</services>
</container>

View File

@ -330,6 +330,7 @@ class ConfigurationTest extends TestCase
'default_bus' => null,
'buses' => ['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]],
],
'disallow_search_engine_index' => true,
];
}
}

View File

@ -1327,6 +1327,27 @@ abstract class FrameworkExtensionTest extends TestCase
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
}
public function testRobotsTagListenerIsRegisteredInDebugMode()
{
$container = $this->createContainer(['kernel.debug' => true]);
(new FrameworkExtension())->load([], $container);
$this->assertTrue($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should be registered');
$definition = $container->getDefinition('disallow_search_engine_index_response_listener');
$this->assertTrue($definition->hasTag('kernel.event_subscriber'), 'DisallowRobotsIndexingListener should have the correct tag');
$container = $this->createContainer(['kernel.debug' => true]);
(new FrameworkExtension())->load([['disallow_search_engine_index' => false]], $container);
$this->assertFalse(
$container->has('disallow_search_engine_index_response_listener'),
'DisallowRobotsIndexingListener should not be registered when explicitly disabled'
);
$container = $this->createContainer(['kernel.debug' => false]);
(new FrameworkExtension())->load([], $container);
$this->assertFalse($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should NOT be registered');
}
protected function createContainer(array $data = [])
{
return new ContainerBuilder(new ParameterBag(array_merge([

View File

@ -12,6 +12,7 @@ CHANGELOG
* the base `DataCollector` doesn't implement `Serializable` anymore, you should
store all the serialized state in the data property instead
* `DumpDataCollector` has been marked as `final`
* added an event listener to prevent search engines from indexing applications in debug mode.
4.2.0
-----

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Ensures that the application is not indexed by search engines.
*
* @author Gary PEGEOT <garypegeot@gmail.com>
*/
class DisallowRobotsIndexingListener implements EventSubscriberInterface
{
private const HEADER_NAME = 'X-Robots-Tag';
public function onResponse(FilterResponseEvent $event): void
{
if (!$event->getResponse()->headers->has(static::HEADER_NAME)) {
$event->getResponse()->headers->set(static::HEADER_NAME, 'noindex');
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => ['onResponse', -255],
];
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Tests\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class DisallowRobotsIndexingListenerTest extends TestCase
{
/**
* @dataProvider provideResponses
*/
public function testInvoke(?string $expected, Response $response): void
{
$listener = new DisallowRobotsIndexingListener();
$event = new FilterResponseEvent($this->createMock(HttpKernelInterface::class), $this->createMock(Request::class), KernelInterface::MASTER_REQUEST, $response);
$listener->onResponse($event);
$this->assertSame($expected, $response->headers->get('X-Robots-Tag'), 'Header doesn\'t match expectations');
}
public function provideResponses(): iterable
{
yield 'No header' => ['noindex', new Response()];
yield 'Header already set' => [
'something else',
new Response('', 204, ['X-Robots-Tag' => 'something else']),
];
}
}