-
Notifications
You must be signed in to change notification settings - Fork 16
Optionally enable caching of any request method #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
52b1777
e0c1c0e
0a3b7c8
8151701
baf4fbd
8d9d48c
5b21d4b
cfa6135
8d8f8e9
fbc1dc7
e94b74a
65d819d
10da16c
9703885
490da8b
727cbf0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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('/'); | ||
|
@@ -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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use short array syntax (StyleCI is turned off for spec files because of the snake_case). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was following the CS of the rest of the file. Long |
||
$response->getHeader('Expires')->willReturn(array())->shouldBeCalled(); | ||
$response->getHeader('ETag')->willReturn(array())->shouldBeCalled(); | ||
|
||
$pool->getItem('e4311a9af932c603b400a54efab21b6d7dea7a90')->shouldBeCalled()->willReturn($item); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please split this too |
||
$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) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
} | ||
|
||
|
@@ -205,7 +205,6 @@ private function getCacheControlDirective(ResponseInterface $response, $name) | |
$headers = $response->getHeader('Cache-Control'); | ||
foreach ($headers as $header) { | ||
if (preg_match(sprintf('|%s=?([0-9]+)?|i', $name), $header, $matches)) { | ||
|
||
// return the value for $name if it exists | ||
if (isset($matches[1])) { | ||
return $matches[1]; | ||
|
@@ -225,6 +224,10 @@ 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()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't like that we specifically do this for POST (as i want to support configuring all request methods as cacheable). i think using the body in hash should not be an issue - its usually just empty. technically, GET requests can have a body as well, for example with elasticsearch. so its actually an improvement to also use the body for the hash. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree on this one too. However some might consider changing the way how keys are generated a BC break. See discussion in #12. Although if I read it correctly the consensus in the end was this would not be considered a BC break. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i would not consider that a BC break. chances are you replace the cache on a new deployment anyways, and even if not, its just a cache. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So what's the verdict? Do we change this to allow any methods? |
||
} | ||
|
||
return hash($this->config['hash_algo'], $request->getMethod().' '.$request->getUri()); | ||
} | ||
|
||
|
@@ -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'])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think once we allow to configure, we should allow any methods. we need a big warning sign for this anyways, as people should know what they do before caching post and other potentially modifying requests... for example, it could make sense to cache a PROPFIND request (webdav, its a non-modifying request)... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. Question is since RFC2616 says valid request method can be pretty much any string (not sure if A..Z or alphanumeric) should any request method be allowed or just the common methods defined in RFC2616-sec9 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'd not do any validation apart from requiring an array of strings. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Found the spec. RFC2616 says request method should be a token and RFC7230 defines token to be any visible |
||
}); | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please format this according to PSR-1/2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There were some other PSR-2 related problems too so I made a separate PR #25.