Skip to content

Commit 21438b3

Browse files
committed
sanity check paths in path based invalidation commands
1 parent 1fa011d commit 21438b3

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

src/Command/InvalidatePathCommand.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
*/
2424
class InvalidatePathCommand extends BaseInvalidateCommand
2525
{
26+
use PathSanityCheck;
27+
2628
/**
2729
* @var string
2830
*/
@@ -73,6 +75,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
7375
$paths = $input->getArgument('paths');
7476

7577
foreach ($paths as $path) {
78+
if ($this->looksLikeRegularExpression($path)) {
79+
$output->writeln(sprintf('Path %s looks like a regular expression. Invalidation requests operate on exact paths. Use regex invalidation for regular expressions.', $path));
80+
}
81+
7682
$this->getCacheManager()->invalidatePath($path);
7783
}
7884
}

src/Command/PathSanityCheck.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSHttpCacheBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\HttpCacheBundle\Command;
13+
14+
use FOS\HttpCache\Exception\InvalidArgumentException;
15+
16+
trait PathSanityCheck
17+
{
18+
/**
19+
* Check if the path looks like a regular expression.
20+
*
21+
* A sane path is non-empty and and contains no characters that are usually
22+
* found in regular expressions: does not start with ^ or end with $ and
23+
* does not contain the patterns .* or .+ or ().
24+
*
25+
* @param string $path
26+
*
27+
* @return bool Whether the path looks like it could be a regular expression
28+
*/
29+
private function looksLikeRegularExpression($path)
30+
{
31+
if (strlen($path) < 1) {
32+
throw new InvalidArgumentException('Path to invalidate can not be empty. To invalidate the root path, use "/"');
33+
}
34+
35+
if ($path[0] === '^'
36+
|| substr($path, -1) === '$'
37+
|| preg_match('/(\.[\*\+]|\(|\))/', $path)
38+
) {
39+
return true;
40+
}
41+
42+
return false;
43+
}
44+
}

src/Command/RefreshPathCommand.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
*/
2424
class RefreshPathCommand extends BaseInvalidateCommand
2525
{
26+
use PathSanityCheck;
27+
2628
/**
2729
* @var string
2830
*/
@@ -73,6 +75,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
7375
$paths = $input->getArgument('paths');
7476

7577
foreach ($paths as $path) {
78+
if ($this->looksLikeRegularExpression($path)) {
79+
$output->writeln(sprintf('Path %s looks like a regular expression. Refresh requests operate with actual requests and thus use exact paths. Use regex invalidation for regular expressions.', $path));
80+
}
81+
7682
$this->getCacheManager()->refreshPath($path);
7783
}
7884
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FOSHttpCacheBundle package.
5+
*
6+
* (c) FriendsOfSymfony <http://friendsofsymfony.github.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 FOS\HttpCacheBundle\Tests\Unit\Command;
13+
14+
use FOS\HttpCacheBundle\Command\PathSanityCheck;
15+
16+
class PathSanityCheckTest extends \PHPUnit_Framework_TestCase
17+
{
18+
public function pathProvider()
19+
{
20+
return [
21+
[false, '/foo'],
22+
[false, '/foo?bar=^'],
23+
[false, '/foo?bar=$€'],
24+
[false, '/foo?bar[baz]=42'],
25+
[true, '^/foo'],
26+
[true, 'foo$'],
27+
[true, '/foo/(bar|baz)'],
28+
];
29+
}
30+
31+
/**
32+
* @dataProvider pathProvider
33+
*/
34+
public function testLooksLikeRegularExpression($expected, $path)
35+
{
36+
$sanityChecking = new SanityChecking();
37+
$this->assertEquals($expected, $sanityChecking->looksLikeRegularExpression($path));
38+
}
39+
}
40+
41+
class SanityChecking
42+
{
43+
use PathSanityCheck {
44+
looksLikeRegularExpression as traitFunction;
45+
}
46+
47+
public function looksLikeRegularExpression($path)
48+
{
49+
return $this->traitFunction($path);
50+
}
51+
}

0 commit comments

Comments
 (0)