Skip to content

Commit

Permalink
tests(v3.0): apply breaking changes to HttpCache
Browse files Browse the repository at this point in the history
  • Loading branch information
Jérôme Deuchnord committed May 13, 2022
1 parent 5fbfd94 commit 15ac863
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 167 deletions.
15 changes: 3 additions & 12 deletions src/HttpCache/EventListener/AddHeadersListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace ApiPlatform\HttpCache\EventListener;

use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
//use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Util\RequestAttributesExtractor;
use Symfony\Component\HttpKernel\Event\ResponseEvent;

Expand All @@ -31,18 +31,16 @@ final class AddHeadersListener
private $sharedMaxAge;
private $vary;
private $public;
private $resourceMetadataFactory;
private $staleWhileRevalidate;
private $staleIfError;

public function __construct(bool $etag = false, int $maxAge = null, int $sharedMaxAge = null, array $vary = null, bool $public = null, ResourceMetadataFactoryInterface $resourceMetadataFactory = null, int $staleWhileRevalidate = null, int $staleIfError = null)
public function __construct(bool $etag = false, int $maxAge = null, int $sharedMaxAge = null, array $vary = null, bool $public = null, int $staleWhileRevalidate = null, int $staleIfError = null)
{
$this->etag = $etag;
$this->maxAge = $maxAge;
$this->sharedMaxAge = $sharedMaxAge;
$this->vary = $vary;
$this->public = $public;
$this->resourceMetadataFactory = $resourceMetadataFactory;
$this->staleWhileRevalidate = $staleWhileRevalidate;
$this->staleIfError = $staleIfError;
}
Expand All @@ -65,14 +63,7 @@ public function onKernelResponse(ResponseEvent $event): void
return;
}

$resourceCacheHeaders = [];

if ($this->resourceMetadataFactory) {
$resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']);
$resourceCacheHeaders = $resourceMetadata->getOperationAttribute($attributes, 'cache_headers', [], true);
} else {
$resourceCacheHeaders = $attributes['cache_headers'] ?? [];
}
$resourceCacheHeaders = $attributes['cache_headers'] ?? [];

if ($this->etag && !$response->getEtag()) {
$response->setEtag(md5((string) $response->getContent()));
Expand Down
1 change: 0 additions & 1 deletion src/Symfony/Bundle/Resources/config/http_cache.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<argument>%api_platform.http_cache.shared_max_age%</argument>
<argument>%api_platform.http_cache.vary%</argument>
<argument>%api_platform.http_cache.public%</argument>
<argument>null</argument>

<tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" priority="-1" />
</service>
Expand Down
17 changes: 2 additions & 15 deletions src/Util/AttributesExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,14 @@ public static function extractAttributes(array $attributes): array
$result['subresource_context'] = $subresourceContext;
}

// // Normalizing identifiers tuples
// // TODO: 3.0 remove
// $identifiers = [];
// foreach (($attributes['_api_identifiers'] ?? ['id']) as $parameterName => $identifiedBy) {
// if (\is_string($identifiedBy)) {
// $identifiers[$identifiedBy] = [$result['resource_class'], $identifiedBy];
// } else {
// $identifiers[$parameterName] = $identifiedBy;
// }
// }
//
// $result['identifiers'] = $identifiers;

if (null === $result['resource_class']) {
return [];
}

$hasRequestAttributeKey = false;
if (isset($attributes['_api_operation_name'])) {
if (isset($attributes['_api_item_operation_name'])) {
$hasRequestAttributeKey = true;
$result['operation_name'] = $attributes['_api_operation_name'];
$result['operation_name'] = $attributes['_api_item_operation_name'];
}
if (isset($attributes['_api_operation'])) {
$result['operation'] = $attributes['_api_operation'];
Expand Down
141 changes: 2 additions & 139 deletions tests/HttpCache/EventListener/AddHeadersListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

namespace ApiPlatform\Tests\HttpCache\EventListener;

use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
use ApiPlatform\HttpCache\EventListener\AddHeadersListener;
use ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy;
use ApiPlatform\Tests\ProphecyTrait;
Expand Down Expand Up @@ -108,10 +106,7 @@ public function testAddHeaders()
$response
);

$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30);
$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, 15, 30);
$listener->onKernelResponse($event);

$this->assertSame('"9893532233caff98cd083a116b013c0b"', $response->getEtag());
Expand All @@ -134,143 +129,11 @@ public function testDoNotSetHeaderWhenAlreadySet()
$response
);

$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn(new ResourceMetadata())->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30);
$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, 15, 30);
$listener->onKernelResponse($event);

$this->assertSame('"etag"', $response->getEtag());
$this->assertSame('max-age=300, public, s-maxage=400, stale-if-error=30, stale-while-revalidate=15', $response->headers->get('Cache-Control'));
$this->assertSame(['Accept', 'Cookie', 'Accept-Encoding'], $response->getVary());
}

public function testSetHeadersFromResourceMetadata()
{
$response = new Response('some content', 200, ['Vary' => ['Accept', 'Cookie']]);
$event = new ResponseEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']),
\defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST,
$response
);

$metadata = new ResourceMetadata(null, null, null, null, null, ['cache_headers' => ['max_age' => 123, 'shared_max_age' => 456, 'stale_while_revalidate' => 928, 'stale_if_error' => 70, 'vary' => ['Vary-1', 'Vary-2']]]);
$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], true, $factory->reveal(), 15, 30);
$listener->onKernelResponse($event);

$this->assertSame('max-age=123, public, s-maxage=456, stale-if-error=70, stale-while-revalidate=928', $response->headers->get('Cache-Control'));
$this->assertSame(['Accept', 'Cookie', 'Vary-1', 'Vary-2'], $response->getVary());
}

public function testSetHeadersFromResourceMetadataMarkedAsPrivate()
{
$response = new Response('some content', 200);
$event = new ResponseEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']),
\defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST,
$response
);

$metadata = new ResourceMetadata(null, null, null, null, null, [
'cache_headers' => [
'max_age' => 123,
'public' => false,
'shared_max_age' => 456,
],
]);
$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal());
$listener->onKernelResponse($event);

$this->assertSame('max-age=123, private', $response->headers->get('Cache-Control'));

// resource's cache marked as private must not contain s-maxage
$this->assertStringNotContainsString('s-maxage', $response->headers->get('Cache-Control'));
}

public function testSetHeadersFromResourceMetadataMarkedAsPublic()
{
$response = new Response('some content', 200);
$event = new ResponseEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']),
\defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST,
$response
);

$metadata = new ResourceMetadata(null, null, null, null, null, [
'cache_headers' => [
'max_age' => 123,
'public' => true,
'shared_max_age' => 456,
],
]);
$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal());
$listener->onKernelResponse($event);

$this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control'));
}

public function testSetHeadersFromResourceMetadataWithNoPrivacy()
{
$response = new Response('some content', 200);
$event = new ResponseEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']),
\defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST,
$response
);

$metadata = new ResourceMetadata(null, null, null, null, null, [
'cache_headers' => [
'max_age' => 123,
'shared_max_age' => 456,
],
]);
$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, [], true, $factory->reveal());
$listener->onKernelResponse($event);

$this->assertSame('max-age=123, public, s-maxage=456', $response->headers->get('Cache-Control'));
}

public function testSetHeadersFromResourceMetadataWithNoPrivacyDefaultsPrivate()
{
$response = new Response('some content', 200);
$event = new ResponseEvent(
$this->prophesize(HttpKernelInterface::class)->reveal(),
new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get']),
\defined(HttpKernelInterface::class.'::MAIN_REQUEST') ? HttpKernelInterface::MAIN_REQUEST : HttpKernelInterface::MASTER_REQUEST,
$response
);

$metadata = new ResourceMetadata(null, null, null, null, null, [
'cache_headers' => [
'max_age' => 123,
'shared_max_age' => 456,
],
]);
$factory = $this->prophesize(ResourceMetadataFactoryInterface::class);
$factory->create(Dummy::class)->willReturn($metadata)->shouldBeCalled();

$listener = new AddHeadersListener(true, 100, 200, ['Accept', 'Accept-Encoding'], false, $factory->reveal());
$listener->onKernelResponse($event);

$this->assertSame('max-age=123, private', $response->headers->get('Cache-Control'));

// resource's cache marked as private must not contain s-maxage
$this->assertStringNotContainsString('s-maxage', $response->headers->get('Cache-Control'));
}
}

0 comments on commit 15ac863

Please sign in to comment.