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 10, 2017
1 parent 9ea1714 commit 52b1777
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# Change Log

## 1.3.0 - unreleased
### Added

- New `methods` setting which allows to configure the request methods which can be cached.

## 1.2.0 - 2016-08-16

### Changed

- The default value for `default_ttl` is changed from `null` to `0`.
- The default value for `default_ttl` is changed from `null` to `0`.

### Fixed

Expand Down
45 changes: 44 additions & 1 deletion 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,6 +97,49 @@ function it_doesnt_store_post_requests(CacheItemPoolInterface $pool, CacheItemIn
$this->handleRequest($request, $next, function () {});
}

function it_stores_post_requests_when_allowed(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response, StreamFactory $streamFactory, StreamInterface $stream)
{
$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('POST');
$request->getUri()->willReturn('/post');
$request->getBody()->willReturn($stream);

$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($stream);
$response->getHeader('Cache-Control')->willReturn(array())->shouldBeCalled();
$response->getHeader('Expires')->willReturn(array())->shouldBeCalled();
$response->getHeader('ETag')->willReturn(array())->shouldBeCalled();

$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();

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

$next = function (RequestInterface $request) use ($response) {
return new FulfilledPromise($response->getWrappedObject());
};

$this->handleRequest($request, $next, function () {});
}

function it_calculate_age_from_response(CacheItemPoolInterface $pool, CacheItemInterface $item, RequestInterface $request, ResponseInterface $response, StreamInterface $stream)
{
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 52b1777

Please sign in to comment.