-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #193 from FriendsOfSymfony/symfony-cache-client
adding client for the symfony built-in reverse proxy HttpCache
- Loading branch information
Showing
14 changed files
with
867 additions
and
237 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
Changelog | ||
========= | ||
|
||
1.3.3 | ||
----- | ||
|
||
* **2015-05-08** Added a client for the Symfony built-in HttpCache | ||
|
||
1.3.0 | ||
----- | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the FOSHttpCache package. | ||
* | ||
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace FOS\HttpCache\ProxyClient; | ||
|
||
use FOS\HttpCache\Exception\InvalidArgumentException; | ||
use FOS\HttpCache\Exception\MissingHostException; | ||
use FOS\HttpCache\ProxyClient\Invalidation\BanInterface; | ||
use FOS\HttpCache\ProxyClient\Invalidation\PurgeInterface; | ||
use FOS\HttpCache\ProxyClient\Invalidation\RefreshInterface; | ||
use FOS\HttpCache\SymfonyCache\PurgeSubscriber; | ||
use Guzzle\Http\ClientInterface; | ||
use Symfony\Component\OptionsResolver\OptionsResolver; | ||
|
||
/** | ||
* Symfony HttpCache invalidator. | ||
* | ||
* @author David de Boer <david@driebit.nl> | ||
* @author David Buchmann <mail@davidbu.ch> | ||
*/ | ||
class Symfony extends AbstractProxyClient implements PurgeInterface, RefreshInterface | ||
{ | ||
const HTTP_METHOD_REFRESH = 'GET'; | ||
|
||
/** | ||
* The options configured in the constructor argument or default values. | ||
* | ||
* @var array | ||
*/ | ||
private $options; | ||
|
||
/** | ||
* {@inheritDoc} | ||
* | ||
* When creating the client, you can configure options: | ||
* | ||
* - purge_method: HTTP method that identifies purge requests. | ||
* | ||
* @param array $options The purge_method that should be used. | ||
*/ | ||
public function __construct(array $servers, $baseUrl = null, ClientInterface $client = null, array $options = array()) | ||
{ | ||
parent::__construct($servers, $baseUrl, $client); | ||
|
||
$resolver = new OptionsResolver(); | ||
$resolver->setDefaults(array( | ||
'purge_method' => PurgeSubscriber::DEFAULT_PURGE_METHOD, | ||
)); | ||
|
||
$this->options = $resolver->resolve($options); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function purge($url, array $headers = array()) | ||
{ | ||
$this->queueRequest($this->options['purge_method'], $url, $headers); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function refresh($url, array $headers = array()) | ||
{ | ||
$headers = array_merge($headers, array('Cache-Control' => 'no-cache')); | ||
$this->queueRequest(self::HTTP_METHOD_REFRESH, $url, $headers); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function getAllowedSchemes() | ||
{ | ||
return array('http', 'https'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the FOSHttpCache package. | ||
* | ||
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace FOS\HttpCache\Test\Proxy; | ||
|
||
/** | ||
* Controls the Symfony HttpCache proxy server. | ||
* | ||
* SYMFONY_CACHE_DIR directory to use for cache | ||
* (default sys_get_temp_dir() + '/foshttpcache-symfony') | ||
*/ | ||
class SymfonyProxy implements ProxyInterface | ||
{ | ||
/** | ||
* Get Symfony cache directory | ||
* | ||
* @return string | ||
*/ | ||
public function getCacheDir() | ||
{ | ||
return defined('SYMFONY_CACHE_DIR') ? SYMFONY_CACHE_DIR : sys_get_temp_dir() . '/foshttpcache-symfony'; | ||
} | ||
|
||
/** | ||
* Start the proxy server | ||
*/ | ||
public function start() | ||
{ | ||
$this->clear(); | ||
} | ||
|
||
/** | ||
* Stop the proxy server | ||
*/ | ||
public function stop() | ||
{ | ||
// nothing to do | ||
} | ||
|
||
/** | ||
* Clear all cached content from the proxy server | ||
*/ | ||
public function clear() | ||
{ | ||
if (is_dir($this->getCacheDir())) { | ||
$path = realpath($this->getCacheDir()); | ||
if (!$this->getCacheDir() || '/' == $path) { | ||
throw new \Exception('Invalid test setup, the cache dir is ' . $path); | ||
} | ||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { | ||
system('DEL /S '.$path); | ||
} else { | ||
system('rm -r '.$path); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the FOSHttpCache package. | ||
* | ||
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace FOS\HttpCache\Test; | ||
|
||
use FOS\HttpCache\ProxyClient\Symfony; | ||
use FOS\HttpCache\Test\Proxy\SymfonyProxy; | ||
|
||
/** | ||
* A phpunit base class to write functional tests with the symfony HttpCache. | ||
* | ||
* The webserver with symfony is to be started with the WebServerListener. | ||
* | ||
* You can define constants in your phpunit to control how this test behaves. | ||
* | ||
* To define constants in the phpunit file, use this syntax: | ||
* <php> | ||
* <const name="WEB_SERVER_PORT" value="/tmp/foo" /> | ||
* </php> | ||
* | ||
* WEB_SERVER_PORT port the PHP webserver listens on (default 8080) | ||
* | ||
* Note that the SymfonyProxy also defines a SYMFONY_CACHE_DIR constant. | ||
*/ | ||
abstract class SymfonyTestCase extends ProxyTestCase | ||
{ | ||
/** | ||
* @var Symfony | ||
*/ | ||
protected $proxyClient; | ||
|
||
/** | ||
* @var SymfonyProxy | ||
*/ | ||
protected $proxy; | ||
|
||
/** | ||
* Get server port | ||
* | ||
* @return int | ||
* | ||
* @throws \Exception | ||
*/ | ||
protected function getCachingProxyPort() | ||
{ | ||
if (!defined('WEB_SERVER_PORT')) { | ||
throw new \Exception('Set WEB_SERVER_PORT in your phpunit.xml'); | ||
} | ||
|
||
return WEB_SERVER_PORT; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function getProxy() | ||
{ | ||
if (null === $this->proxy) { | ||
$this->proxy = new SymfonyProxy(); | ||
} | ||
|
||
return $this->proxy; | ||
} | ||
|
||
/** | ||
* Get Symfony proxy client | ||
* | ||
* We use a non-default method for PURGE because the built-in PHP webserver | ||
* does not allow arbitrary HTTP methods. | ||
* https://github.com/php/php-src/blob/PHP-5.4.1/sapi/cli/php_http_parser.c#L78-L102 | ||
* | ||
* @return Symfony | ||
*/ | ||
protected function getProxyClient() | ||
{ | ||
if (null === $this->proxyClient) { | ||
$this->proxyClient = new Symfony( | ||
array('http://127.0.0.1:' . $this->getCachingProxyPort()), | ||
$this->getHostName() . ':' . $this->getCachingProxyPort(), | ||
null, | ||
array('purge_method' => 'NOTIFY') | ||
); | ||
} | ||
|
||
return $this->proxyClient; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace FOS\HttpCache\Tests\Functional\Fixtures\Symfony; | ||
|
||
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache; | ||
use Symfony\Component\HttpFoundation\Request; | ||
use Symfony\Component\HttpKernel\HttpKernelInterface; | ||
|
||
class AppCache extends EventDispatchingHttpCache | ||
{ | ||
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) | ||
{ | ||
$response = parent::handle($request, $type, $catch); | ||
|
||
if ($response->headers->has('X-Symfony-Cache')) { | ||
if (false !== strpos($response->headers->get('X-Symfony-Cache'), 'miss')) { | ||
$state = 'MISS'; | ||
} elseif (false !== strpos($response->headers->get('X-Symfony-Cache'), 'fresh')) { | ||
$state = 'HIT'; | ||
} else { | ||
$state = 'UNDETERMINED'; | ||
} | ||
$response->headers->set('X-Cache', $state); | ||
} | ||
|
||
return $response; | ||
} | ||
} |
Oops, something went wrong.