8000 [HttpKernel] Start an implementation of the PSR6 store for HttpCache · symfony/symfony@8a4c89b · GitHub
[go: up one dir, main page]

Skip to content

Commit 8a4c89b

Browse files
committed
[HttpKernel] Start an implementation of the PSR6 store for HttpCache
1 parent fd0d288 commit 8a4c89b

File tree

3 files changed

+466
-0
lines changed

3 files changed

+466
-0
lines changed
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
<?php
2+
3+
namespace Symfony\Component\HttpKernel\HttpCache;
4+
5+
use Psr\Cache\CacheItemPoolInterface;
6+
use Symfony\Component\Cache\CacheItem;
7+
use Symfony\Component\HttpFoundation\Request;
8+
use Symfony\Component\HttpFoundation\Response;
9+
10+
final class Psr6Store implements StoreInterface
11+
{
12+
/**
13+
* @var CacheItemPoolInterface
14+
*/
15+
private $cachePool;
16+
17+
/**
18+
* List of locks acquired by the current process.
19+
*
20+
* @var array
21+
*/
22+
private $locks = array();
23+
24+
/**
25+
* @param CacheItemPoolInterface $cachePool
26+
*/
27+
public function __construct(CacheItemPoolInterface $cachePool)
28+
{
29+
$this->cachePool = $cachePool;
30+
}
31+
32+
/**
33+
* Locates a cached Response for the Request provided.
34+
*
35+
* @param Request $request A Request instance
36+
*
37+
* @return Response|null A Response instance, or null if no cache entry was found
38+
*/
39+
public function lookup(Request $request)
40+
{
41+
// TODO: Implement lookup() method.
42+
}
43+
44+
/**
45+
* Writes a cache entry to the store for the given Request and Response.
46+
*
47+
* Existing entries are read and any that match the response are removed. This
48+
* method calls write with the new list of cache entries.
49+
*
50+
* @param Request $request A Request instance
51+
* @param Response $response A Response instance
52+
*
53+
* @return string The key under which the response is stored
54+
*/
55+
public function write(Request $request, Response $response)
56+
{
57+
if (!$response->headers->has('X-Content-Digest')) {
58+
$contentDigest = $this->generateContentDigest($response);
59+
60+
if (false === $this->save($contentDigest, $response->getContent())) {
61+
throw new \RuntimeException('Unable to store the entity.');
62+
}
63+
64+
$response->headers->set('X-Content-Digest', $contentDigest);
65+
66+
if (!$response->headers->has('Transfer-Encoding')) {
67+
$response->headers->set('Content-Length', strlen($response->getContent()));
68+
}
69+
}
70+
71+
$key = $this->getCacheKey($request);
72+
$headers = $response->headers->all();
73+
unset($headers['age']);
74+
75+
$this->save($key, serialize(array(array($request->headers->all(), $headers))));
76+
}
77+
78+
/**
79+
* Invalidates all cache entries that match the request.
80+
*
81+
* @param Request $request A Request instance
82+
*/
83+
public function invalidate(Request $request)
84+
{
85+
// TODO: Implement invalidate() method.
86+
}
87+
88+
/**
89+
* Locks the cache for a given Request.
90+
*
91+
* @param Request $request A Request instance
92+
*
93+
* @return bool|string true if the lock is acquired, the path to the current lock otherwise
94+
*/
95+
public function lock(Request $request)
96+
{
97+
$lockKey = $this->getLockKey($request);
98+
99+
if (isset($this->locks[$lockKey])) {
100+
return true;
101+
}
102+
103+
$item = $this->cachePool->getItem($lockKey);
104+
105+
if ($item->isHit()) {
106+
return false;
107+
}
108+
109+
$this->cachePool->save($item);
110+
111+
$this->locks[$lockKey] = true;
112+
113+
return true;
114+
}
115+
116+
/**
117+
* Releases the lock for the given Request.
118+
*
119+
* @param Request $request A Request instance
120+
*
121+
* @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
122+
*/
123+
public function unlock(Request $request)
124+
{
125+
$lockKey = $this->getLockKey($request);
126+
127+
if (!isset($this->locks[$lockKey])) {
128+
return false;
129+
}
130+
131+
$this->cachePool->deleteItem($lockKey);
132+
133+
unset($this->locks[$lockKey]);
134+
135+
return true;
136+
}
137+
138+
/**
139+
* Returns whether or not a lock exists.
140+
*
141+
* @param Request $request A Request instance
142+
*
143+
* @return bool true if lock exists, false otherwise
144+
*/
145+
public function isLocked(Request $request)
146+
{
147+
$lockKey = $this->getLockKey($request);
148+
149+
if (isset($this->locks[$lockKey])) {
150+
return true;
151+
}
152+
153+
return $this->cachePool->hasItem($this->getLockKey($request));
154+
}
155+
156+
/**
157+
* Purges data for the given URL.
158+
*
159+
* @param string $url A URL
160+
*
161+
* @return bool true if the URL exists and has been purged, false otherwise
162+
*/
163+
public function purge($url)
164+
{
165+
// TODO: Implement purge() method.
166+
}
167+
168+
/**
169+
* Cleanups storage.
170+
*/
171+
public function cleanup()
172+
{
173+
$this->cachePool->deleteItems(array_keys($this->locks));
174+
$this->locks = array();
175+
}
176+
177+
/**
178+
* @param Request $request
179+
*
180+
* @return string
181+
*/
182+
private function getCacheKey(Request $request)
183+
{
184+
return 'md'.hash('sha256', $request->getUri());
185+
}
186+
187+
/**
188+
* @param Request $request
189+
*
190+
* @return string
191+
*/
192+
private function getLockKey(Request $request)
193+
{
194+
return $this->getCacheKey($request).'.lock';
195+
}
196+
197+
/**
198+
* @param Response $response
199+
*
200+
* @return string
201+
*/
202+
private function generateContentDigest(Response $response)
203+
{
204+
return 'en'.hash('sha256', $response->getContent());
205+
}
206+
207+
/**
208+
* @param string $key
209+
* @param string $data
210+
*
211+
* @return bool
212+
*/
213+
private function save($key, $data)
214+
{
215+
return $this->cachePool->save($this->createCacheItem($key, $data));
216+
}
217+
218+
/**
219+
* @param string $key
220+
* @param mixed $value
221+
* @param bool $isHit
222+
*
223+
* @return CacheItem
224+
*/
225+
private function createCacheItem($key, $value, $isHit = false)
226+
{
227+
$f = \Closure::bind(
228+
function ($key, $value, $isHit) {
229+
$item = new CacheItem();
230+
$item->key = $key;
231+
$item->value = $value;
232+
$item->isHit = $isHit;
233+
234+
return $item;
235+
},
236+
null,
237+
CacheItem::class
238+
);
239+
240+
return $f($key, $value, $isHit);
241+
}
242+
}

0 commit comments

Comments
 (0)
0