Skip to content

Commit

Permalink
Merge pull request #28 from jolicode/feature/new-blacklisters-tweaks
Browse files Browse the repository at this point in the history
Blacklisters tweaks
  • Loading branch information
pyrech authored Oct 12, 2017
2 parents b3f767f + 91c4d35 commit 83bfbcb
Show file tree
Hide file tree
Showing 18 changed files with 211 additions and 180 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* [BC BREAK] Remove SeoManagerInterface
* Add blacklist behaviour to avoid useless fetcher runs
* Add blacklisters checking for XHR or HTTP methods

## 0.4.0 (2017-09-12)

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ changes, improvements or alternatives may be given).
Run the tests using the following script:

```shell
vendor/bin/phpunit
composer test
```

## Standard code
Expand Down
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@
"branch-alias": {
"dev-master": "0.x-dev"
}
},
"scripts": {
"test": [
"SYMFONY_PHPUNIT_REMOVE=\"symfony/yaml\" vendor/bin/simple-phpunit"
]
}
}
2 changes: 1 addition & 1 deletion doc/symfony/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Note:
### Blacklist

You can blacklist some request/response to avoid fetcher to run (f.e. on non
2xx response, on your admin, etc).
2xx response, on your admin, on XHR calls, etc).

There is some built-in blacklister that you can enable/configure via the config
`blacklist`:
Expand Down
30 changes: 30 additions & 0 deletions doc/symfony/available-blacklisters.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
|---|---|---|
| not_2xx | Blacklist if the response status code is not 2xx | None |
| path | Blacklist if the request path matches the pattern | - "pattern": mandatory, the regex pattern to match |
| not_method | Blacklist if the request HTTP method is in the accepted ones | - "method": mandatory, the HTTP method(s) to accept |
| xml_http | Blacklist if the request is made through XmlHttpRequest | None |

## not_2xx

Expand Down Expand Up @@ -36,3 +38,31 @@ seo_override:
type: path
pattern: '^/(admin|account)'
```

## not_method

The `not_method` blacklister refuses request whose method is not in the
configured `method` option. This option can be a single HTTP method or an array
of methods:

```yaml
seo_override:
blacklist:
-
type: not_method
method: [GET, POST]
# if only one method should be accepted
# method: GET
```

## xml_http

The `xml_http` blacklister refuses request which have been made through Ajax
(XmlHttpRequest). This blacklister does not have any option so the short YAML
syntax can be used:

```yaml
seo_override:
blacklist:
- xml_http
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,27 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* Class GetBlacklister.
*/
class GetMethodBlacklister implements Blacklister
class NotMethodBlacklister implements Blacklister
{
/** @var string[] */
private $methods;

/**
* @param Request $request
* @param Response $response
*
* @return bool
* @param string|string[] $method
*/
public function __construct($method)
{
$this->methods = (array) $method;
}

public function isBlacklisted(Request $request, Response $response): bool
{
return $request->isMethod('get');
foreach ($this->methods as $method) {
if ($request->isMethod($method)) {
return false;
}
}

return true;
}
}
33 changes: 0 additions & 33 deletions src/Bridge/Symfony/Blacklister/PostMethodBlacklister.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/Bridge/Symfony/Blacklister/XmlHttpBlacklister.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,8 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* Class XmlHttpBlacklister.
*/
class XmlHttpBlacklister implements Blacklister
{
/**
* @param Request $request
* @param Response $response
*
* @return bool
*/
public function isBlacklisted(Request $request, Response $response): bool
{
return $request->isXmlHttpRequest();
Expand Down
16 changes: 6 additions & 10 deletions src/Bridge/Symfony/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,13 @@ services:
tags:
- { name: seo_override.blacklister, alias: not_2xx }

seo_override.blacklister.get_method:
class: Joli\SeoOverride\Bridge\Symfony\Blacklister\GetMethodBlacklister
public: false
tags:
- { name: seo_override.blacklister, alias: get_method }

seo_override.blacklister.post_method:
class: Joli\SeoOverride\Bridge\Symfony\Blacklister\PostMethodBlacklister
seo_override.blacklister.not_method:
class: Joli\SeoOverride\Bridge\Symfony\Blacklister\NotMethodBlacklister
public: false
arguments:
- '' # Argument configured in the DIC extension
tags:
- { name: seo_override.blacklister, alias: post_method }
- { name: seo_override.blacklister, alias: not_method, required_options: 'method' }

seo_override.blacklister.xml_http:
class: Joli\SeoOverride\Bridge\Symfony\Blacklister\XmlHttpBlacklister
Expand All @@ -74,6 +70,6 @@ services:
class: Joli\SeoOverride\Bridge\Symfony\Blacklister\PathBlacklister
public: false
arguments:
- ''
- '' # Argument configured in the DIC extension
tags:
- { name: seo_override.blacklister, alias: path, required_options: 'pattern' }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<html>
<head>
<!--SEO_TITLE--><title>old title for admin</title><!--/SEO_TITLE-->
<meta name="description" content="description for admin" />
</head>
<body>
<h1>Hello admin</h1>
</body>
</html>
11 changes: 9 additions & 2 deletions tests/Functional/Fixtures/symfony/app/config/config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
app.error_controller:
class: Joli\SeoOverride\Tests\Functional\Fixtures\symfony\src\Controller\ErrorController
app.controller:
class: Joli\SeoOverride\Tests\Functional\Fixtures\symfony\src\Controller\AppController
calls:
- [setContainer, ["@service_container"]]

Expand Down Expand Up @@ -40,10 +40,17 @@ seo_override:
'':
'/error':
title: 'new title for error page'
'/admin':
title: 'new title for admin'
-
type: php
include_path: "%kernel.root_dir%/config/seo_overrides.php"
domains:
domain_doctrine: 'domain_doctrine.com'
domain_in_memory: 'domain_in_memory.com'
domain_php: 'domain_php.com'
blacklist:
- not_2xx
- { type: path, pattern: '^/admin' }
- { type: not_method, method: ['GET', 'POST'] }
- xml_http
9 changes: 7 additions & 2 deletions tests/Functional/Fixtures/symfony/app/config/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ index:
error:
path: /error
defaults:
_controller: app.error_controller:errorAction
_controller: app.controller:errorAction

download:
path: /download
defaults:
_controller: app.error_controller:downloadAction
_controller: app.controller:downloadAction

admin:
path: /admin
defaults:
_controller: app.controller:adminAction
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;

class ErrorController extends Controller
class AppController extends Controller
{
public function errorAction()
{
Expand All @@ -19,4 +19,9 @@ public function downloadAction()

return new BinaryFileResponse($tmpfname);
}

public function adminAction()
{
return new Response($this->renderView('admin.html.twig'), 200);
}
}
75 changes: 56 additions & 19 deletions tests/Functional/SymfonyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@

class SymfonyTest extends KernelTestCase
{
const NOT_OVERRIDDEN_HOMEPAGE_CONTENT = <<<'HTML'
<html>
<head>
<title>old title for homepage</title>
<meta name="description" content="description for homepage" />
</head>
<body>
<h1>Hello world</h1>
</body>
</html>

HTML;

public static function setUpBeforeClass()
{
parent::setUpBeforeClass();
Expand Down Expand Up @@ -119,64 +132,88 @@ public function test_it_overrides_seo_handled_with_php_fetcher()
}

public function test_it_does_not_override_seo_when_no_fetcher_matching()
{
$response = $this->call('/', 'domain_unkown.com');

$this->assertSame(self::NOT_OVERRIDDEN_HOMEPAGE_CONTENT, $response->getContent());
}

public function test_it_does_not_override_seo_when_no_content_or_binary_response()
{
$response = $this->call('/download', 'localhost');

$this->assertSame(200, $response->getStatusCode());
$this->assertSame(false, $response->getContent());
}

public function test_it_does_not_override_seo_when_no_2XX_response()
{
$expected = <<<'HTML'
<html>
<head>
<title>old title for homepage</title>
<meta name="description" content="description for homepage" />
<title>old title for error page</title>
<meta name="description" content="description for error page" />
</head>
<body>
<h1>Hello world</h1>
<h1>Hello error</h1>
</body>
</html>

HTML;
$response = $this->call('/error', 'localhost');

$response = $this->call('/', 'domain_unkown.com');

$this->assertSame(400, $response->getStatusCode());
$this->assertSame($expected, $response->getContent());
}

public function test_it_does_not_override_seo_when_no_2XX_response()
public function test_it_does_not_override_seo_when_request_path_does_not_match()
{
$expected = <<<'HTML'
<html>
<head>
<title>old title for error page</title>
<meta name="description" content="description for error page" />
<title>old title for admin</title>
<meta name="description" content="description for admin" />
</head>
<body>
<h1>Hello error</h1>
<h1>Hello admin</h1>
</body>
</html>

HTML;
$response = $this->call('/admin', 'localhost');

$response = $this->call('/error', 'localhost');

$this->assertSame(400, $response->getStatusCode());
$this->assertSame(200, $response->getStatusCode());
$this->assertSame($expected, $response->getContent());
}

public function test_it_does_not_override_seo_when_no_content_or_binary_response()
public function test_it_does_not_override_seo_when_request_use_not_allowed_action()
{
$response = $this->call('/download', 'localhost');
$response = $this->call('/', 'localhost', 'PUT');

$this->assertSame(200, $response->getStatusCode());
$this->assertSame(false, $response->getContent());
$this->assertSame(self::NOT_OVERRIDDEN_HOMEPAGE_CONTENT, $response->getContent());
}

public function test_it_does_not_override_seo_when_request_is_xhr()
{
$response = $this->call('/', 'localhost', 'GET', [
'X-Requested-With' => 'XMLHttpRequest',
]);

$this->assertSame(200, $response->getStatusCode());
$this->assertSame(self::NOT_OVERRIDDEN_HOMEPAGE_CONTENT, $response->getContent());
}

protected static function getKernelClass()
{
return AppKernel::class;
}

private function call($uri, $host)
private function call(string $uri, string $host, string $method = 'GET', array $server = [])
{
$request = Request::create($uri, 'GET', [], [], [], [
'HTTP_HOST' => $host,
]);
$server['HTTP_HOST'] = $host;

$request = Request::create($uri, $method, [], [], [], $server);

return self::$kernel->handle($request);
}
Expand Down
Loading

0 comments on commit 83bfbcb

Please sign in to comment.