11<?php
22namespace Flowpack \FullPageCache \Http ;
33
4- use Flowpack \FullPageCache \Aspects \ContentCacheAspect ;
5- use Flowpack \FullPageCache \Cache \MetadataAwareStringFrontend ;
64use Neos \Cache \Frontend \StringFrontend ;
75use Neos \Flow \Annotations as Flow ;
86use Neos \Flow \Http \Component \ComponentContext ;
@@ -20,95 +18,57 @@ class RequestStorageComponent implements ComponentInterface
2018 */
2119 protected $ cacheFrontend ;
2220
23- /**
24- * @Flow\Inject
25- * @var MetadataAwareStringFrontend
26- */
27- protected $ contentCache ;
28-
2921 /**
3022 * @var boolean
3123 * @Flow\InjectConfiguration(path="enabled")
3224 */
3325 protected $ enabled ;
3426
35- /**
36- * @Flow\Inject
37- * @var ContentCacheAspect
38- */
39- protected $ contentCacheAspect ;
40-
4127 /**
4228 * @inheritDoc
4329 */
4430 public function handle (ComponentContext $ componentContext )
4531 {
46- if (!$ this ->enabled ) {
47- return ;
48- }
49-
5032 $ request = $ componentContext ->getHttpRequest ();
51- if (strtoupper ($ request ->getMethod ()) !== 'GET ' ) {
52- return ;
53- }
54-
55- if (!empty ($ request ->getUri ()->getQuery ())) {
56- return ;
57- }
58-
5933 $ response = $ componentContext ->getHttpResponse ();
6034
6135 if ($ response ->hasHeader ('X-From-FullPageCache ' )) {
6236 return ;
6337 }
6438
65- if ($ this ->contentCacheAspect ->hasUncachedSegments ())
66- {
67- return ;
68- }
69-
70- if ($ response ->hasHeader ('Set-Cookie ' )) {
71- return ;
72- }
73-
74- $ entryIdentifier = md5 ((string )$ request ->getUri ());
75-
76- [$ tags , $ lifetime ] = $ this ->getCacheTagsAndLifetime ();
77-
78- if (empty ($ tags )) {
79- // For now do not cache something without tags (maybe it was not a Neos page)
80- return ;
81- }
82-
83- $ modifiedResponse = $ response ->withHeader ('X-Storage-Component ' , $ entryIdentifier );
84- $ this ->cacheFrontend ->set ($ entryIdentifier , str ($ modifiedResponse ), $ tags , $ lifetime );
85- // TODO: because stream is copied ot the modifiedResponse we would get empty output on first request
86- $ response ->getBody ()->rewind ();
87- }
88-
89- /**
90- * Get cache tags and lifetime from the cache metadata that was extracted by the special cache frontend for content cache
91- *
92- * @return array with first "tags" and then "lifetime"
93- */
94- protected function getCacheTagsAndLifetime (): array
95- {
96- $ lifetime = null ;
97- $ tags = [];
98- $ entriesMetadata = $ this ->contentCache ->getAllMetadata ();
99- foreach ($ entriesMetadata as $ identifier => $ metadata ) {
100- $ entryTags = isset ($ metadata ['tags ' ]) ? $ metadata ['tags ' ] : [];
101- $ entryLifetime = isset ($ metadata ['lifetime ' ]) ? $ metadata ['lifetime ' ] : null ;
102- if ($ entryLifetime !== null ) {
103- if ($ lifetime === null ) {
104- $ lifetime = $ entryLifetime ;
39+ if ($ response ->hasHeader ('CacheControl ' )) {
40+ $ cacheControl = $ response ->getHeaderLine ('CacheControl ' );
41+ if ($ cacheControl && strpos ($ cacheControl ,'s-maxage= ' ) === 0 ) {
42+ $ lifetime = (int ) substr ($ cacheControl , 10 );
43+ $ cacheTags = $ response ->getHeader ('X-CacheTags ' ) ;
44+
45+ $ entryIdentifier = md5 ((string )$ request ->getUri ());
46+ $ etag = md5 (str ($ response ));
47+
48+ $ modifiedResponse = $ response
49+ ->withoutHeader ('X-CacheTags ' )
50+ ->withoutHeader ('CacheControl ' )
51+ ->withAddedHeader ('ETag ' , $ etag )
52+ ->withAddedHeader ('CacheControl ' , 'max-age= ' . $ lifetime );
53+
54+ $ modifiedResponseforStorage = $ modifiedResponse
55+ ->withHeader ('X-Storage-Component ' , $ entryIdentifier )
56+ ->withHeader ('X-Storage-Timestamp ' , time ())
57+ ->withHeader ('X-Storage-Lifetime ' , $ lifetime );
58+
59+ $ this ->cacheFrontend ->set ($ entryIdentifier , str ($ modifiedResponseforStorage ), $ cacheTags , $ lifetime );
60+ $ response ->getBody ()->rewind ();
61+
62+ $ ifNoneMatch = $ request ->getHeaderLine ('If-None-Match ' );
63+ if ($ ifNoneMatch && $ ifNoneMatch === $ etag ) {
64+ $ notModifiedResponse = (new Response (304 ))
65+ ->withAddedHeader ('CacheControl ' , 'max-age= ' . $ lifetime )
66+ ->withHeader ('X-From-FullPageCache ' , $ entryIdentifier );
67+ $ componentContext ->replaceHttpResponse ($ notModifiedResponse );
10568 } else {
106- $ lifetime = min ( $ lifetime , $ entryLifetime );
69+ $ componentContext -> replaceHttpResponse ( $ modifiedResponse );
10770 }
10871 }
109- $ tags = array_unique (array_merge ($ tags , $ entryTags ));
11072 }
111-
112- return [$ tags , $ lifetime ];
11373 }
11474}
0 commit comments