Skip to content
Permalink
Browse files

feature #30325 [HttpKernel] Prevent search engines from indexing dev …

…applications (GaryPEGEOT)

This PR was squashed before being merged into the 4.3-dev branch (closes #30325).

Discussion
----------

[HttpKernel] Prevent search engines from indexing dev applications

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #30318
| License       | MIT
| Doc PR        | TODO

Add the *X-Robots-Tag: noindex* to dev (and test) applications to prevent search engines to index them.

Commits
-------

3dd8671 [HttpKernel] Prevent search engines from indexing dev applications
  • Loading branch information...
fabpot committed Mar 4, 2019
2 parents 11f1660 + 3dd8671 commit 0034e14463ad4eb1e70bd8de318d7ed8aee0c05a
@@ -108,6 +108,7 @@ public function getConfigTreeBuilder()
$this->addWebLinkSection($rootNode);
$this->addLockSection($rootNode);
$this->addMessengerSection($rootNode);
$this->addRobotsIndexSection($rootNode);
return $treeBuilder;
}
@@ -1156,4 +1157,17 @@ function ($a) {
->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 @@ public function load(array $configs, ContainerBuilder $container)
// 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_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
'default_bus' => null,
'buses' => ['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]],
],
'disallow_search_engine_index' => true,
];
}
}
@@ -1327,6 +1327,27 @@ public function testSessionCookieSecureAuto()
$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']),
];
}
}

0 comments on commit 0034e14

Please sign in to comment.
You can’t perform that action at this time.