@@ -358,19 +358,22 @@ class RoutesSuite extends CatsEffectSuite:
358358 }
359359 }
360360
361- externalIndexHtml.test(" Static files are updated when needed" ) {
361+ externalIndexHtml.test(" Static files are updated when needed and cached otherwise " .only ) {
362362 staticDir =>
363- def cacheFormatTime = fileLastModified((staticDir / " index.html" ).toFs2).map {
364- seconds =>
365- httpCacheFormat(ZonedDateTime .ofInstant(Instant .ofEpochSecond(seconds), ZoneId .of(" GMT" )))
366- }
363+ val cat = os.read.bytes(os.resource / " cat.webp" )
367364
368365 val app = for
369366 logger <- IO (scribe.cats[IO ]).toResource
370367 fileToHashRef <- Ref [IO ].of(Map .empty[String , String ]).toResource
371368 fileToHashMapRef = MapRef .fromSingleImmutableMapRef[IO , String , String ](fileToHashRef)
372369 refreshPub <- Topic [IO , Unit ].toResource
373- // subscriber = refreshPub.subscribe(10).take(5).compile.toList
370+ _ <- IO .blocking(os.write(staticDir / " image.webp" , cat)).toResource
371+ modifedAt <- fileLastModified((staticDir / " index.html" ).toFs2)
372+ .map {
373+ seconds =>
374+ httpCacheFormat(ZonedDateTime .ofInstant(Instant .ofEpochSecond(seconds), ZoneId .of(" GMT" )))
375+ }
376+ .toResource
374377 theseRoutes <- routes(
375378 os.temp.dir().toString,
376379 refreshPub,
@@ -379,40 +382,35 @@ class RoutesSuite extends CatsEffectSuite:
379382 fileToHashRef,
380383 None
381384 )(logger)
382- yield (theseRoutes.orNotFound, logger)
385+ yield (theseRoutes.orNotFound, logger, modifedAt )
383386
384- app
385- .both(cacheFormatTime.toResource)
386- .use {
387- case ((served, logger), firstModified) =>
388- val request1 = org.http4s.Request [IO ](uri = org.http4s.Uri .unsafeFromString(" /index.html" ))
387+ app.use {
388+ case (served, logger, firstModified) =>
389+ val request1 = org.http4s.Request [IO ](uri = org.http4s.Uri .unsafeFromString(" /image.webp" ))
389390
390- val request2 = org
391- .http4s
392- .Request [IO ](uri = org.http4s.Uri .unsafeFromString(" /index.html " ))
393- .withHeaders(
394- org.http4s.Headers .of(org.http4s.Header .Raw (ci " If-Modified-Since " , firstModified.toString()))
395- )
391+ val request2 = org
392+ .http4s
393+ .Request [IO ](uri = org.http4s.Uri .unsafeFromString(" /image.webp " ))
394+ .withHeaders(
395+ org.http4s.Headers .of(org.http4s.Header .Raw (ci " If-Modified-Since " , firstModified.toString()))
396+ )
396397
397- served(request1).flatTap(r => logger.debug(" headers" + r.headers.headers.mkString(" ," ))) >>
398- logger.trace(" first modified " + firstModified) >>
399- // You need these ... otherwise no caching.
400- // https://simonhearne.com/2022/caching-header-best-practices/
401- assertIOBoolean(served(request1).map(_.headers.get(ci " ETag " ).isDefined)) >>
402- assertIOBoolean(served(request1).map(_.headers.get(ci " Cache-Control " ).isDefined)) >>
403- assertIOBoolean(served(request1).map(_.headers.get(ci " Expires " ).isDefined)) >>
404- assertIOBoolean(served(request1).map(_.headers.get(ci " Last-Modified " ).isDefined)) >>
405- // Don't forget to set them _all_
406- assertIO(served(request1).map(_.status.code), 200 ) >>
407- assertIO(served(request2).map(_.status.code), 304 ) >>
408- IO .sleep(
409- 1500 .millis
410- ) >> // have to wait at least one second otherwish last modified could be the same, if test took <1 sceond to get to this point
411- IO .blocking(os.write.over(staticDir / " index.html" , """ <head><title>Test</title></head>""" )) >>
412- served(request2).flatMap(_.bodyText.compile.string).flatMap(s => logger.trace(s)) >>
413- assertIO(served(request2).map(_.status.code), 200 )
398+ served(request1).flatTap(r => logger.debug(" headers" + r.headers.headers.mkString(" ," ))) >>
399+ logger.trace(" first modified " + firstModified) >>
400+ // You need these ... otherwise no caching.
401+ // https://simonhearne.com/2022/caching-header-best-practices/
402+ assertIOBoolean(served(request1).map(_.headers.get(ci " ETag " ).isDefined)) >>
403+ assertIOBoolean(served(request1).map(_.headers.get(ci " Cache-Control " ).isDefined)) >>
404+ assertIOBoolean(served(request1).map(_.headers.get(ci " Expires " ).isDefined)) >>
405+ assertIOBoolean(served(request1).map(_.headers.get(ci " Last-Modified " ).isDefined)) >>
406+ // Don't forget to set them _all_
407+ assertIO(served(request1).map(_.status.code), 200 ) >>
408+ assertIO(served(request2).map(_.status.code), 304 ) >>
409+ IO .blocking(os.write.over(staticDir / " image.webp" , os.read.bytes(os.resource / " dog.webp" ))) >>
410+ served(request2).flatMap(_.bodyText.compile.string).flatMap(s => logger.trace(s)) >>
411+ assertIO(served(request2).map(_.status.code), 200 )
414412
415- }
413+ }
416414 }
417415
418416 externalIndexHtml.test(" Client SPA routes return index.html" ) {
0 commit comments