Skip to content

Commit a5d85b0

Browse files
authored
Merge pull request #12 from Sammyjo20/fix/allow-body-to-be-used-in-cache-key
Fix | Allow body to be used in cache key
2 parents 330ba77 + 9ae8ae1 commit a5d85b0

File tree

7 files changed

+106
-28
lines changed

7 files changed

+106
-28
lines changed

.github/workflows/php-cs-fixer.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ jobs:
1818

1919
steps:
2020
- name: Checkout code
21-
uses: actions/checkout@v2
22-
with:
23-
ref: ${{ github.head_ref }}
24-
token: ${{ secrets.PHP_CS_FIXER }}
21+
uses: actions/checkout@v3
2522
- name: Run PHP CS Fixer
2623
uses: docker://oskarstark/php-cs-fixer-ga
2724
with:

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
},
2323
"require-dev": {
2424
"friendsofphp/php-cs-fixer": "^3.13",
25-
"pestphp/pest": "^1.21.2",
25+
"pestphp/pest": "^2.3",
2626
"spatie/ray": "^1.34.2",
2727
"league/flysystem": "^3.12.2",
2828
"orchestra/testbench": "^8.0",

phpunit.xml

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
4-
bootstrap="vendor/autoload.php"
5-
colors="true"
6-
>
7-
<testsuites>
8-
<testsuite name="Test Suite">
9-
<directory suffix="Test.php">./tests</directory>
10-
</testsuite>
11-
</testsuites>
12-
<coverage processUncoveredFiles="true">
13-
<include>
14-
<directory suffix=".php">./app</directory>
15-
<directory suffix=".php">./src</directory>
16-
</include>
17-
</coverage>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" cacheDirectory=".phpunit.cache">
3+
<testsuites>
4+
<testsuite name="Test Suite">
5+
<directory suffix="Test.php">./tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<coverage>
9+
<include>
10+
<directory suffix=".php">./app</directory>
11+
<directory suffix=".php">./src</directory>
12+
</include>
13+
</coverage>
1814
</phpunit>

src/Http/Middleware/CacheMiddleware.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function __construct(
2626
protected Driver $driver,
2727
protected int $ttl,
2828
protected ?string $cacheKey,
29-
protected bool $invalidate = false,
29+
protected bool $invalidate = false,
3030
) {
3131
//
3232
}
@@ -53,7 +53,7 @@ public function __invoke(PendingRequest $pendingRequest): ?SimulatedResponsePayl
5353
// the SimulatedResponsePayload here.
5454

5555
if ($this->invalidate === false && $cachedResponse->hasNotExpired()) {
56-
$pendingRequest->middleware()->onResponse(fn (Response $response) => $response->setCached(true));
56+
$pendingRequest->middleware()->onResponse(fn (Response $response) => $response->setCached(true), true);
5757

5858
return $cachedResponse->getSimulatedResponsePayload();
5959
}

src/Traits/HasCaching.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,17 @@ public function bootHasCaching(PendingRequest $pendingRequest): void
5858
? $request->cacheExpiryInSeconds()
5959
: $connector->cacheExpiryInSeconds();
6060

61-
// Register a request middleware which wil handle the caching and recording
62-
// of real responses for caching.
61+
// Register a request middleware which wil handle the caching
62+
// and recording of real responses for caching.
6363

64-
$pendingRequest->middleware()->onRequest(
65-
callable: new CacheMiddleware($cacheDriver, $cacheExpiryInSeconds, $this->cacheKey($pendingRequest), $this->invalidateCache),
66-
);
64+
$pendingRequest->middleware()->onRequest(function (PendingRequest $middlewarePendingRequest) use ($cacheDriver, $cacheExpiryInSeconds) {
65+
// We'll call the cache middleware invokable class with the $middlewarePendingRequest
66+
// because this $pendingRequest has everything loaded, unlike the instance that
67+
// the plugin is provided. This allows us to have access to body and merged
68+
// properties.
69+
70+
return call_user_func(new CacheMiddleware($cacheDriver, $cacheExpiryInSeconds, $this->cacheKey($middlewarePendingRequest), $this->invalidateCache), $middlewarePendingRequest);
71+
});
6772
}
6873

6974
/**

tests/Feature/CacheTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Saloon\CachePlugin\Tests\Fixtures\Connectors\CachedConnector;
1212
use Saloon\CachePlugin\Tests\Fixtures\Requests\CachedPostRequest;
1313
use Saloon\CachePlugin\Tests\Fixtures\Requests\CachedUserRequest;
14+
use Saloon\CachePlugin\Tests\Fixtures\Requests\BodyCacheKeyRequest;
1415
use Saloon\CachePlugin\Tests\Fixtures\Requests\CachedConnectorRequest;
1516
use Saloon\CachePlugin\Tests\Fixtures\Requests\AllowedCachedPostRequest;
1617
use Saloon\CachePlugin\Tests\Fixtures\Requests\CustomKeyCachedUserRequest;
@@ -186,6 +187,37 @@
186187
expect($responseC->isCached())->toBeFalse();
187188
});
188189

190+
test('body can be used in the cache key', function () {
191+
$mockClient = new MockClient([
192+
MockResponse::make(['name' => 'Sam']),
193+
MockResponse::make(['name' => 'Gareth']),
194+
]);
195+
196+
$requestA = new BodyCacheKeyRequest;
197+
$requestA->body()->set([
198+
'name' => 'Sam',
199+
'expiry' => '10 hours',
200+
]);
201+
202+
$responseA = TestConnector::make()->send($requestA, $mockClient);
203+
204+
expect($responseA->isCached())->toBeFalse();
205+
expect($responseA->json())->toEqual(['name' => 'Sam']);
206+
expect($responseA->status())->toEqual(200);
207+
208+
$requestB = new BodyCacheKeyRequest;
209+
$requestB->body()->set([
210+
'name' => 'Sam',
211+
'expiry' => '10 hours',
212+
]);
213+
214+
$responseB = TestConnector::make()->send($requestB, $mockClient);
215+
216+
expect($responseB->isCached())->toBeTrue();
217+
expect($responseB->json())->toEqual(['name' => 'Sam']);
218+
expect($responseB->status())->toEqual(200);
219+
});
220+
189221
test('you will not receive a cached response if the response has expired', function () {
190222
$mockClient = new MockClient([
191223
MockResponse::make(['name' => 'Sam']),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Saloon\CachePlugin\Tests\Fixtures\Requests;
6+
7+
use Saloon\Enums\Method;
8+
use Saloon\Http\Request;
9+
use League\Flysystem\Filesystem;
10+
use Saloon\Contracts\Body\HasBody;
11+
use Saloon\Traits\Body\HasJsonBody;
12+
use Saloon\Contracts\PendingRequest;
13+
use Saloon\CachePlugin\Contracts\Driver;
14+
use Saloon\CachePlugin\Traits\HasCaching;
15+
use Saloon\CachePlugin\Contracts\Cacheable;
16+
use Saloon\CachePlugin\Drivers\FlysystemDriver;
17+
use League\Flysystem\Local\LocalFilesystemAdapter;
18+
use Saloon\CachePlugin\Tests\Fixtures\Connectors\TestConnector;
19+
20+
class BodyCacheKeyRequest extends Request implements Cacheable, HasBody
21+
{
22+
use HasCaching;
23+
use HasJsonBody;
24+
25+
protected ?string $connector = TestConnector::class;
26+
27+
protected Method $method = Method::GET;
28+
29+
public function resolveEndpoint(): string
30+
{
31+
return '/user';
32+
}
33+
34+
public function resolveCacheDriver(): Driver
35+
{
36+
return new FlysystemDriver(new Filesystem(new LocalFilesystemAdapter(cachePath())));
37+
}
38+
39+
public function cacheExpiryInSeconds(): int
40+
{
41+
return 60;
42+
}
43+
44+
protected function cacheKey(PendingRequest $pendingRequest): ?string
45+
{
46+
return (string)$pendingRequest->body()->all();
47+
}
48+
}

0 commit comments

Comments
 (0)