[HttpKernel] Prevent search engines from indexing dev applications
This commit is contained in:
parent
1ad6f6f319
commit
3dd86719bf
|
@ -108,6 +108,7 @@ class Configuration implements ConfigurationInterface
|
||||||
$this->addWebLinkSection($rootNode);
|
$this->addWebLinkSection($rootNode);
|
||||||
$this->addLockSection($rootNode);
|
$this->addLockSection($rootNode);
|
||||||
$this->addMessengerSection($rootNode);
|
$this->addMessengerSection($rootNode);
|
||||||
|
$this->addRobotsIndexSection($rootNode);
|
||||||
|
|
||||||
return $treeBuilder;
|
return $treeBuilder;
|
||||||
}
|
}
|
||||||
|
@ -1156,4 +1157,17 @@ class Configuration implements ConfigurationInterface
|
||||||
->end()
|
->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()
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,6 +394,10 @@ class FrameworkExtension extends Extension
|
||||||
// remove tagged iterator argument for resource checkers
|
// remove tagged iterator argument for resource checkers
|
||||||
$container->getDefinition('config_cache_factory')->setArguments([]);
|
$container->getDefinition('config_cache_factory')->setArguments([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$config['disallow_search_engine_index'] ?? false) {
|
||||||
|
$container->removeDefinition('disallow_search_engine_index_response_listener');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -85,5 +85,8 @@
|
||||||
<argument type="service" id="controller_name_converter" />
|
<argument type="service" id="controller_name_converter" />
|
||||||
<tag name="kernel.event_subscriber" />
|
<tag name="kernel.event_subscriber" />
|
||||||
</service>
|
</service>
|
||||||
|
<service id="disallow_search_engine_index_response_listener" class="Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener">
|
||||||
|
<tag name="kernel.event_subscriber" />
|
||||||
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
||||||
|
|
|
@ -330,6 +330,7 @@ class ConfigurationTest extends TestCase
|
||||||
'default_bus' => null,
|
'default_bus' => null,
|
||||||
'buses' => ['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]],
|
'buses' => ['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]],
|
||||||
],
|
],
|
||||||
|
'disallow_search_engine_index' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1327,6 +1327,27 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||||
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
|
$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 = [])
|
protected function createContainer(array $data = [])
|
||||||
{
|
{
|
||||||
return new ContainerBuilder(new ParameterBag(array_merge([
|
return new ContainerBuilder(new ParameterBag(array_merge([
|
||||||
|
|
|
@ -12,6 +12,7 @@ CHANGELOG
|
||||||
* the base `DataCollector` doesn't implement `Serializable` anymore, you should
|
* the base `DataCollector` doesn't implement `Serializable` anymore, you should
|
||||||
store all the serialized state in the data property instead
|
store all the serialized state in the data property instead
|
||||||
* `DumpDataCollector` has been marked as `final`
|
* `DumpDataCollector` has been marked as `final`
|
||||||
|
* added an event listener to prevent search engines from indexing applications in debug mode.
|
||||||
|
|
||||||
4.2.0
|
4.2.0
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -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],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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']),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue