2727use Symfony \Component \Filesystem \Filesystem ;
2828use Symfony \Component \HttpFoundation \BinaryFileResponse ;
2929use Symfony \Component \HttpFoundation \File \File ;
30+ use Symfony \Component \HttpFoundation \Request ;
3031use Symfony \Component \HttpKernel \Exception \NotFoundHttpException ;
3132use function Safe \file_put_contents ;
3233use function Safe \tempnam ;
@@ -69,7 +70,7 @@ public function throwsNotFoundWhenMetadataNotFound(): void
6970 $ this ->expectException (NotFoundHttpException::class);
7071 $ this ->expectExceptionMessage ('Asset not found ' );
7172
72- $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
73+ $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
7374 }
7475
7576 #[Test]
@@ -101,7 +102,7 @@ public function returnsFileWhenAlreadyDownloaded(): void
101102
102103 $ controller = new CdnController ($ storage , $ downloader , null , null , null );
103104
104- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
105+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
105106
106107 self ::assertInstanceOf (BinaryFileResponse::class, $ response );
107108 self ::assertSame (200 , $ response ->getStatusCode ());
@@ -158,7 +159,7 @@ public function downloadsFileWhenNotYetDownloaded(): void
158159
159160 $ controller = new CdnController ($ storage , $ downloader , null , null , null );
160161
161- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
162+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
162163
163164 self ::assertInstanceOf (BinaryFileResponse::class, $ response );
164165 self ::assertSame (200 , $ response ->getStatusCode ());
@@ -190,7 +191,7 @@ public function throwsExceptionWhenDownloadedMetadataIncomplete(): void
190191 $ this ->expectException (\RuntimeException::class);
191192 $ this ->expectExceptionMessage ('Downloaded file metadata is incomplete ' );
192193
193- $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
194+ $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
194195 }
195196
196197 #[Test]
@@ -214,7 +215,7 @@ public function setsContentTypeHeader(): void
214215
215216 $ controller = new CdnController ($ storage , $ downloader , null , null , null );
216217
217- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'webp ' );
218+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'webp ' );
218219
219220 self ::assertSame ('image/webp ' , $ response ->headers ->get ('Content-Type ' ));
220221 }
@@ -241,7 +242,7 @@ public function setsEtagHeader(): void
241242
242243 $ controller = new CdnController ($ storage , $ downloader , null , null , null );
243244
244- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
245+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
245246
246247 self ::assertSame ('"etag-value-123" ' , $ response ->getEtag ());
247248 }
@@ -267,7 +268,7 @@ public function setsMaxAgeWhenConfigured(): void
267268
268269 $ controller = new CdnController ($ storage , $ downloader , 3600 , null , null );
269270
270- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
271+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
271272
272273 self ::assertSame (3600 , $ response ->getMaxAge ());
273274 }
@@ -293,7 +294,7 @@ public function setsSharedMaxAgeWhenConfigured(): void
293294
294295 $ controller = new CdnController ($ storage , $ downloader , null , 7200 , null );
295296
296- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
297+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
297298
298299 self ::assertStringContainsString ('s-maxage=7200 ' , (string ) $ response ->headers ->get ('Cache-Control ' ));
299300 }
@@ -319,7 +320,7 @@ public function setsPublicCacheDirective(): void
319320
320321 $ controller = new CdnController ($ storage , $ downloader , null , null , true );
321322
322- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
323+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
323324
324325 self ::assertStringContainsString ('public ' , (string ) $ response ->headers ->get ('Cache-Control ' ));
325326 }
@@ -345,7 +346,7 @@ public function setsPrivateCacheDirective(): void
345346
346347 $ controller = new CdnController ($ storage , $ downloader , null , null , false );
347348
348- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
349+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
349350
350351 self ::assertStringContainsString ('private ' , (string ) $ response ->headers ->get ('Cache-Control ' ));
351352 }
@@ -371,14 +372,44 @@ public function combinesAllCacheDirectives(): void
371372
372373 $ controller = new CdnController ($ storage , $ downloader , 3600 , 7200 , true );
373374
374- $ response = $ controller ->__invoke ('ef7436441c4defbf ' , 'image ' , 'jpg ' );
375+ $ response = $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
375376
376377 $ cacheControl = (string ) $ response ->headers ->get ('Cache-Control ' );
377378 self ::assertStringContainsString ('public ' , $ cacheControl );
378379 self ::assertStringContainsString ('max-age=3600 ' , $ cacheControl );
379380 self ::assertStringContainsString ('s-maxage=7200 ' , $ cacheControl );
380381 }
381382
383+ #[Test]
384+ public function returns304WhenEtagMatches (): void
385+ {
386+ $ tempFile = $ this ->createTempFile ('content ' );
387+ $ file = new File ($ tempFile );
388+
389+ $ metadata = new CdnFileMetadata (
390+ originalUrl: 'https://a.storyblok.com/f/12345/image.jpg ' ,
391+ contentType: 'image/jpeg ' ,
392+ etag: '"etag-value-123" ' ,
393+ expiresAt: new DateTimeImmutable ('+1 day ' ),
394+ );
395+
396+ $ storage = self ::createMock (CdnStorageInterface::class);
397+ $ storage ->method ('getMetadata ' )->willReturn ($ metadata );
398+ $ storage ->method ('hasFile ' )->willReturn (true );
399+ $ storage ->method ('getFile ' )->willReturn ($ file );
400+
401+ $ downloader = self ::createMock (FileDownloaderInterface::class);
402+
403+ $ controller = new CdnController ($ storage , $ downloader , null , null , null );
404+
405+ $ request = new Request ();
406+ $ request ->headers ->set ('If-None-Match ' , '"etag-value-123" ' );
407+
408+ $ response = $ controller ->__invoke ($ request , 'ef7436441c4defbf ' , 'image ' , 'jpg ' );
409+
410+ self ::assertSame (304 , $ response ->getStatusCode ());
411+ }
412+
382413 #[Test]
383414 public function constructsFullFilenameFromParts (): void
384415 {
@@ -406,7 +437,7 @@ public function constructsFullFilenameFromParts(): void
406437
407438 $ controller = new CdnController ($ storage , $ downloader , null , null , null );
408439
409- $ controller ->__invoke ('ef7436441c4defbf ' , 'my-document ' , 'pdf ' );
440+ $ controller ->__invoke (new Request (), 'ef7436441c4defbf ' , 'my-document ' , 'pdf ' );
410441 }
411442
412443 private function createTempFile (string $ content ): string
0 commit comments