8000 [HttpKernel] Prevent search engines from indexing dev applications · symfony/symfony@3dd8671 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3dd8671

Browse files
GaryPEGEOTfabpot
authored andcommitted
[HttpKernel] Prevent search engines from indexing dev applications
1 parent 1ad6f6f commit 3dd8671

File tree

8 files changed

+134
-0
lines changed

8 files changed

+134
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public function getConfigTreeBuilder()
108108
$this->addWebLinkSection($rootNode);
109109
$this->addLockSection($rootNode);
110110
$this->addMessengerSection($rootNode);
111+
$this->addRobotsIndexSection($rootNode);
111112

112113
return $treeBuilder;
113114
}
@@ -1156,4 +1157,17 @@ function ($a) {
11561157
->end()
11571158
;
11581159
}
1160+
1161+
private function addRobotsIndexSection(ArrayNodeDefinition $rootNode)
1162+
{
1163+
$rootNode
1164+
->children()
1165+
->booleanNode('disallow_search_engine_index')
1166+
->info('Enabled by default when debug is enabled.')
1167+
->defaultValue($this->debug)
1168+
->treatNullLike($this->debug)
1169+
->end()
1170+
->end()
1171+
;
1172+
}
11591173
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ public function load(array $configs, ContainerBuilder $container)
394394
// remove tagged iterator argument for resource checkers
395395
$container->getDefinition('config_cache_factory')->setArguments([]);
396396
}
397+
398+
if (!$config['disallow_search_engine_index'] ?? false) {
399+
$container->removeDefinition('disallow_search_engine_index_response_listener');
400+
}
397401
}
398402

399403
/**

src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,8 @@
8585
<argument type="service" id="controller_name_converter" />
8686 8000
<tag name="kernel.event_subscriber" />
8787
</service>
88+
<service id="disallow_search_engine_index_response_listener" class="Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener">
89+
<tag name="kernel.event_subscriber" />
90+
</service>
8891
</services>
8992
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphor
330330
'default_bus' => null,
331331
'buses' => ['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]],
332332
],
333+
'disallow_search_engine_index' => true,
333334
];
334335
}
335336
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,27 @@ public function testSessionCookieSecureAuto()
13271327
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
13281328
}
13291329

1330+
public function testRobotsTagListenerIsRegisteredInDebugMode()
1331+
{
1332+
$container = $this->createContainer(['kernel.debug' => true]);
1333+
(new FrameworkExtension())->load([], $container);
1334+
$this->assertTrue($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should be registered');
1335+
1336+
$definition = $container->getDefinition('disallow_search_engine_index_response_listener');
1337+
$this->assertTrue($definition->hasTag('kernel.event_subscriber'), 'DisallowRobotsIndexingListener should have the correct tag');
1338+
1339+
$container = $this->createContainer(['kernel.debug' => true]);
1340+
(new FrameworkExtension())->load([['disallow_search_engine_index' => false]], $container);
1341+
$this->assertFalse(
1342+
$container->has('disallow_search_engine_index_response_listener'),
1343+
'DisallowRobotsIndexingListener should not be registered when explicitly disabled'
1344+
);
1345+
1346+
$container = $this->createContainer(['kernel.debug' => false]);
1347+
(new FrameworkExtension())->load([], $container);
1348+
$this->assertFalse($container->has('disallow_search_engine_index_response_listener'), 'DisallowRobotsIndexingListener should NOT be registered');
1349+
}
1350+
13301351
protected function createContainer(array $data = [])
13311352
{
13321353
return new ContainerBuilder(new ParameterBag(array_merge([

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
* the base `DataCollector` doesn't implement `Serializable` anymore, you should
1313
store all the serialized state in the data property instead
1414
* `DumpDataCollector` has been marked as `final`
15+
* added an event listener to prevent search engines from indexing applications in debug mode.
1516

1617
4.2.0
1718
-----
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
16+
use Symfony\Component\HttpKernel\KernelEvents;
17+
18+
/**
19+
* Ensures that the application is not indexed by search engines.
20+
*
21+
* @author Gary PEGEOT <garypegeot@gmail.com>
22+
*/
23+
class DisallowRobotsIndexingListener implements EventSubscriberInterface
24+
{
25+
private const HEADER_NAME = 'X-Robots-Tag';
26+
27+
public function onResponse(FilterResponseEvent $event): void
28+
{
29+
if (!$event->getResponse()->headers->has(static::HEADER_NAME)) {
30+
$event->getResponse()->headers->set(static::HEADER_NAME, 'noindex');
31+
}
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public static function getSubscribedEvents()
38+
{
39+
return [
40+
KernelEvents::RESPONSE => ['onResponse', -255],
41+
];
42+
}
43+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Tests\EventListener;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpFoundation\Response;
17+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
18+
use Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener;
19+
use Symfony\Component\HttpKernel\HttpKernelInterface;
20+
use Symfony\Component\HttpKernel\KernelInterface;
21+
22+
class DisallowRobotsIndexingListenerTest extends TestCase
23+
{
24+
/**
25+
* @dataProvider provideResponses
26+
*/
27+
public function testInvoke(?string $expected, Response $response): void
28+
{
29+
$listener = new DisallowRobotsIndexingListener();
30+
31+
$event = new FilterResponseEvent($this->createMock(HttpKernelInterface::class), $this->createMock(Request::class), KernelInterface::MASTER_REQUEST, $response);
32+
33+
$listener->onResponse($event);
34+
35+
$this->assertSame($expected, $response->headers->get('X-Robots-Tag'), 'Header doesn\'t match expectations');
36+
}
37+
38+
public function provideResponses(): iterable
39+
{
40+
yield 'No header' => ['noindex', new Response()];
41+
42+
yield 'Header already set' => [
43+
'something else',
44+
new Response('', 204, ['X-Robots-Tag' => 'something else']),
45+
];
46+
}
47+
}

0 commit comments

Comments
 (0)
0