Skip to content

Commit 0e12dcc

Browse files
authored
use __serialize instead of __sleep on CacheEntry (#163)
1 parent 8528f8c commit 0e12dcc

File tree

2 files changed

+80
-31
lines changed

2 files changed

+80
-31
lines changed

src/CacheEntry.php

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
namespace Kevinrob\GuzzleCache;
44

55
use GuzzleHttp\Psr7\PumpStream;
6+
use Psr\Http\Message\MessageInterface;
67
use Psr\Http\Message\RequestInterface;
78
use Psr\Http\Message\ResponseInterface;
89

9-
class CacheEntry
10+
class CacheEntry implements \Serializable
1011
{
1112
/**
1213
* @var RequestInterface
@@ -256,47 +257,72 @@ public function getAge()
256257
return time() - $this->dateCreated->getTimestamp();
257258
}
258259

259-
public function __sleep()
260+
public function __serialize(): array
260261
{
261-
// Stream/Resource can't be serialized... So we copy the content into an implementation of `Psr\Http\Message\StreamInterface`
262-
if ($this->response !== null) {
263-
$responseBody = (string)$this->response->getBody();
264-
$this->response = $this->response->withBody(
265-
new PumpStream(
266-
new BodyStore($responseBody),
267-
[
268-
'size' => mb_strlen($responseBody),
269-
]
270-
)
271-
);
272-
}
262+
return [
263+
'request' => self::toSerializeableMessage($this->request),
264+
'response' => $this->response !== null ? self::toSerializeableMessage($this->response) : null,
265+
'staleAt' => $this->staleAt,
266+
'staleIfErrorTo' => $this->staleIfErrorTo,
267+
'staleWhileRevalidateTo' => $this->staleWhileRevalidateTo,
268+
'dateCreated' => $this->dateCreated,
269+
'timestampStale' => $this->timestampStale,
270+
];
271+
}
272+
273+
public function __unserialize(array $data): void
274+
{
275+
$this->request = self::restoreStreamBody($data['request']);
276+
$this->response = $data['response'] !== null ? self::restoreStreamBody($data['response']) : null;
277+
$this->staleAt = $data['staleAt'];
278+
$this->staleIfErrorTo = $data['staleIfErrorTo'];
279+
$this->staleWhileRevalidateTo = $data['staleWhileRevalidateTo'];
280+
$this->dateCreated = $data['dateCreated'];
281+
$this->timestampStale = $data['timestampStale'];
282+
}
283+
284+
/**
285+
* Stream/Resource can't be serialized... So we copy the content into an implementation of `Psr\Http\Message\StreamInterface`
286+
*
287+
* @template T of MessageInterface
288+
*
289+
* @param T $message
290+
* @return T
291+
*/
292+
private static function toSerializeableMessage(MessageInterface $message): MessageInterface
293+
{
294+
$bodyString = (string)$message->getBody();
273295

274-
$requestBody = (string)$this->request->getBody();
275-
$this->request = $this->request->withBody(
296+
return $message->withBody(
276297
new PumpStream(
277-
new BodyStore($requestBody),
298+
new BodyStore($bodyString),
278299
[
279-
'size' => mb_strlen($requestBody)
300+
'size' => mb_strlen($bodyString),
280301
]
281302
)
282303
);
304+
}
283305

284-
return array_keys(get_object_vars($this));
306+
/**
307+
* @template T of MessageInterface
308+
*
309+
* @param T $message
310+
* @return T
311+
*/
312+
private static function restoreStreamBody(MessageInterface $message): MessageInterface
313+
{
314+
return $message->withBody(
315+
\GuzzleHttp\Psr7\Utils::streamFor((string) $message->getBody())
316+
);
285317
}
286318

287-
public function __wakeup()
319+
public function serialize()
288320
{
289-
// We re-create the stream of the response
290-
if ($this->response !== null) {
291-
$this->response = $this->response
292-
->withBody(
293-
\GuzzleHttp\Psr7\Utils::streamFor((string) $this->response->getBody())
294-
);
295-
}
296-
$this->request = $this->request
297-
->withBody(
298-
\GuzzleHttp\Psr7\Utils::streamFor((string) $this->request->getBody())
299-
);
321+
return serialize($this->__serialize());
300322
}
301323

324+
public function unserialize($data)
325+
{
326+
$this->__unserialize(unserialize($data));
327+
}
302328
}

tests/CacheEntryTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,29 @@ public function testCacheEntryShouldBeSerializableWithIgBinaryWithoutWarning()
111111
}
112112
}
113113

114+
public function testSerializationShouldNotMutateCacheEntry()
115+
{
116+
$request = new Request(
117+
'GET',
118+
'test.local',
119+
[],
120+
'Sample body' // Always include a body in the request to be sure there is a stream in it
121+
);
122+
$response = new Response(
123+
200, [
124+
'Cache-Control' => 'max-age=60',
125+
],
126+
'Test content'
127+
);
128+
$cacheEntry = new CacheEntry($request, $response, $this->makeDateTimeOffset(10));
129+
130+
$originalCacheEntry = clone $cacheEntry;
131+
132+
serialize($cacheEntry);
133+
134+
$this->assertEquals($cacheEntry, $originalCacheEntry);
135+
}
136+
114137
private function setResponseHeader($name, $value)
115138
{
116139
$this->responseHeaders[$name] = [$value];

0 commit comments

Comments
 (0)