Skip to content

Commit

Permalink
Enable caching of POST requests when requested
Browse files Browse the repository at this point in the history
This is useful for example when using a HTTPlug based SoapClient.
php-http/client-common#26
  • Loading branch information
tuupola committed Feb 6, 2017
1 parent 9ea1714 commit aa8188e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
46 changes: 26 additions & 20 deletions spec/CachePluginSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function it_doesnt_store_failed_responses(CacheItemPoolInterface $pool, CacheIte
$this->handleRequest($request, $next, function () {});
}

function it_doesnt_store_post_requests(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response)
function it_doesnt_store_post_requests_by_default(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response)
{
$request->getMethod()->willReturn('POST');
$request->getUri()->willReturn('/');
Expand All @@ -97,36 +97,42 @@ function it_doesnt_store_post_requests(CacheItemPoolInterface $pool, CacheItemIn
$this->handleRequest($request, $next, function () {});
}


function it_calculate_age_from_response(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response, StreamInterface $stream)
function it_stores_post_requests_when_allowed(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response, StreamFactory $streamFactory, StreamInterface $stream)
{
$httpBody = 'body';
$this->beConstructedWith($pool, $streamFactory, [
'default_ttl' => 60,
'cache_lifetime' => 1000,
'methods' => ['GET', 'HEAD', 'POST']
]);

$httpBody = 'hello=world';
$stream->__toString()->willReturn($httpBody);
$stream->isSeekable()->willReturn(true);
$stream->rewind()->shouldBeCalled();

$request->getMethod()->willReturn('GET');
$request->getUri()->willReturn('/');
$request->getMethod()->willReturn('POST');
$request->getUri()->willReturn('/post');
$request->getBody()->willReturn($stream);

$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($stream);
$response->getHeader('Cache-Control')->willReturn(array('max-age=40'));
$response->getHeader('Age')->willReturn(array('15'));
$response->getHeader('Expires')->willReturn(array());
$response->getHeader('ETag')->willReturn(array());
$response->getHeader('Cache-Control')->willReturn(array())->shouldBeCalled();
$response->getHeader('Expires')->willReturn(array())->shouldBeCalled();
$response->getHeader('ETag')->willReturn(array())->shouldBeCalled();

$pool->getItem('d20f64acc6e70b6079845f2fe357732929550ae1')->shouldBeCalled()->willReturn($item);
$pool->getItem('e4311a9af932c603b400a54efab21b6d7dea7a90')->shouldBeCalled()->willReturn($item);
$item->isHit()->willReturn(false);
$item->expiresAfter(1060)->willReturn($item)->shouldBeCalled();

$item->set($this->getCacheItemMatcher([
'response' => $response->getWrappedObject(),
'body' => $httpBody,
'expiresAt' => 0,
'createdAt' => 0,
'etag' => []
]))->willReturn($item)->shouldBeCalled();
// 40-15 should be 25 + the default 1000
$item->expiresAfter(1025)->willReturn($item)->shouldBeCalled();
$pool->save($item)->shouldBeCalled();
'response' => $response->getWrappedObject(),
'body' => $httpBody,
'expiresAt' => 0,
'createdAt' => 0,
'etag' => []
]))->willReturn($item)->shouldBeCalled();

$pool->save(Argument::any())->shouldBeCalled();

$next = function (RequestInterface $request) use ($response) {
return new FulfilledPromise($response->getWrappedObject());
Expand Down
10 changes: 9 additions & 1 deletion src/CachePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
{
$method = strtoupper($request->getMethod());
// if the request not is cachable, move to $next
if ($method !== 'GET' && $method !== 'HEAD') {
if (!in_array($method, $this->config['methods'])) {
return $next($request);
}

Expand Down Expand Up @@ -225,6 +225,9 @@ private function getCacheControlDirective(ResponseInterface $response, $name)
*/
private function createCacheKey(RequestInterface $request)
{
if ('POST' === $request->getMethod()) {
return hash($this->config['hash_algo'], $request->getMethod().' '.$request->getUri().' '.$request->getBody());
}
return hash($this->config['hash_algo'], $request->getMethod().' '.$request->getUri());
}

Expand Down Expand Up @@ -273,12 +276,17 @@ private function configureOptions(OptionsResolver $resolver)
'default_ttl' => 0,
'respect_cache_headers' => true,
'hash_algo' => 'sha1',
'methods' => ['GET', 'HEAD'],
]);

$resolver->setAllowedTypes('cache_lifetime', ['int', 'null']);
$resolver->setAllowedTypes('default_ttl', ['int', 'null']);
$resolver->setAllowedTypes('respect_cache_headers', 'bool');
$resolver->setAllowedTypes('methods', 'array');
$resolver->setAllowedValues('hash_algo', hash_algos());
$resolver->setAllowedValues('methods', function ($value) {
return 0 === count(array_diff($value, ['GET', 'HEAD', 'POST']));
});
}

/**
Expand Down

0 comments on commit aa8188e

Please sign in to comment.