[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->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()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -330,6 +330,7 @@ class ConfigurationTest extends TestCase
|
|||
'default_bus' => null,
|
||||
'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()));
|
||||
}
|
||||
|
||||
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([
|
||||
|
|
|
@ -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
|
||||
-----
|
||||
|
|
|
@ -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