@@ -19,6 +19,7 @@ import org.http4s.server.middleware.Logger
1919import org .http4s .server .staticcontent .*
2020import org .http4s .server .staticcontent .FileService
2121import org .typelevel .ci .CIStringSyntax
22+ import org .http4s .EntityBody
2223
2324import fs2 .*
2425import fs2 .concurrent .Topic
@@ -70,8 +71,8 @@ def routes[F[_]: Files: MonadThrow](
7071 ref
7172 )(logger)
7273
73- val hashFalse = vanillaTemplate(false ).render.hashCode.toString
74- val hashTrue = vanillaTemplate(true ).render.hashCode.toString
74+ // val hashFalse = vanillaTemplate(false).render.hashCode.toString
75+ // val hashTrue = vanillaTemplate(true).render.hashCode.toString
7576 val zdt = ZonedDateTime .now()
7677
7778 def userBrowserCacheHeaders (resp : Response [IO ], lastModZdt : ZonedDateTime , injectStyles : Boolean ) =
@@ -97,56 +98,49 @@ def routes[F[_]: Files: MonadThrow](
9798 object StaticHtmlMiddleware :
9899 def apply (service : HttpRoutes [IO ], injectStyles : Boolean )(logger : Scribe [IO ]): HttpRoutes [IO ] = Kleisli {
99100 (req : Request [IO ]) =>
100- req.headers.get(ci " If-None-Match " ).map(_.toList) match
101- case Some (h :: Nil ) if h.value == hashFalse => OptionT .liftF(IO (Response [IO ](Status .NotModified )))
102- case Some (h :: Nil ) if h.value == hashTrue => OptionT .liftF(IO (Response [IO ](Status .NotModified )))
103- case _ => service(req).semiflatMap(userBrowserCacheHeaders(_, zdt, injectStyles))
104- end match
105-
101+ service(req).semiflatMap(userBrowserCacheHeaders(_, zdt, injectStyles))
106102 }
107103
108104 end StaticHtmlMiddleware
109105
110- def generatedIndexHtml (injectStyles : Boolean ) =
106+ def generatedIndexHtml (injectStyles : Boolean , modules : Ref [ IO , Map [ String , String ]] ) =
111107 StaticHtmlMiddleware (
112108 HttpRoutes .of[IO ] {
113109 case req @ GET -> Root =>
114110 logger.trace(" Generated index.html" ) >>
115- IO (
111+ vanillaTemplate(injectStyles, modules).map : html =>
116112 Response [IO ]()
117- .withEntity(vanillaTemplate(injectStyles) )
113+ .withEntity(html )
118114 .withHeaders(
119115 Header .Raw (ci " Cache-Control " , " no-cache" ),
120116 Header .Raw (
121117 ci " ETag " ,
122- injectStyles match
123- case true => hashTrue
124- case false => hashFalse
118+ html.hashCode.toString
125119 ),
126120 Header .Raw (ci " Last-Modified " , formatter.format(zdt)),
127121 Header .Raw (
128122 ci " Expires " ,
129123 httpCacheFormat(ZonedDateTime .ofInstant(Instant .now().plusSeconds(10000000 ), ZoneId .of(" GMT" )))
130124 )
131125 )
132- )
126+
133127 },
134128 injectStyles
135129 )(logger).combineK(
136130 StaticHtmlMiddleware (
137131 HttpRoutes .of[IO ] {
138132 case GET -> Root / " index.html" =>
139- IO {
140- Response [IO ]().withEntity(vanillaTemplate(injectStyles) )
141- }
133+ vanillaTemplate(injectStyles, modules).map : html =>
134+ Response [IO ]().withEntity(html )
135+
142136 },
143137 injectStyles
144138 )(logger)
145139 )
146140
147141 // val formatter = DateTimeFormatter.RFC_1123_DATE_TIME
148- val staticAssetRoutes : HttpRoutes [IO ] = indexOpts match
149- case None => generatedIndexHtml(injectStyles = false )
142+ def staticAssetRoutes ( modules : Ref [ IO , Map [ String , String ]]) : HttpRoutes [IO ] = indexOpts match
143+ case None => generatedIndexHtml(injectStyles = false , modules )
150144
151145 case Some (IndexHtmlConfig .IndexHtmlPath (path)) =>
152146 StaticMiddleware (
@@ -161,9 +155,9 @@ def routes[F[_]: Files: MonadThrow](
161155 Router (
162156 " " -> fileService[IO ](FileService .Config (stylesPath.toString()))
163157 )
164- )(logger).combineK(generatedIndexHtml(injectStyles = true ))
158+ )(logger).combineK(generatedIndexHtml(injectStyles = true , modules ))
165159
166- val clientSpaRoutes : HttpRoutes [IO ] =
160+ def clientSpaRoutes ( modules : Ref [ IO , Map [ String , String ]]) : HttpRoutes [IO ] =
167161 clientRoutingPrefix match
168162 case None => HttpRoutes .empty[IO ]
169163 case Some (spaRoute) =>
@@ -173,9 +167,9 @@ def routes[F[_]: Files: MonadThrow](
173167 StaticHtmlMiddleware (
174168 HttpRoutes .of[IO ] {
175169 case req @ GET -> root /: path =>
176- IO (
177- Response [IO ]().withEntity(vanillaTemplate( false ) )
178- )
170+ vanillaTemplate( false , modules).map : html =>
171+ Response [IO ]().withEntity(html )
172+
179173 },
180174 false
181175 )(logger)
@@ -184,9 +178,8 @@ def routes[F[_]: Files: MonadThrow](
184178 StaticHtmlMiddleware (
185179 HttpRoutes .of[IO ] {
186180 case GET -> root /: spaRoute /: path =>
187- IO (
188- Response [IO ]().withEntity(vanillaTemplate(true ))
189- )
181+ vanillaTemplate(true , modules).map: html =>
182+ Response [IO ]().withEntity(html)
190183 },
191184 true
192185 )(logger)
@@ -195,7 +188,24 @@ def routes[F[_]: Files: MonadThrow](
195188 StaticFileMiddleware (
196189 HttpRoutes .of[IO ] {
197190 case req @ GET -> spaRoute /: path =>
198- StaticFile .fromPath(dir / " index.html" , Some (req)).getOrElseF(NotFound ())
191+ StaticFile
192+ .fromPath(dir / " index.html" , Some (req))
193+ .getOrElseF(NotFound ())
194+ .flatMap {
195+ f =>
196+ f.body
197+ .through(text.utf8.decode)
198+ .compile
199+ .string
200+ .flatMap: body =>
201+ for str <- injectModulePreloads(modules, body)
202+ yield
203+ val bytes = str.getBytes()
204+ f.withEntity(bytes)
205+ f
206+
207+ }
208+
199209 },
200210 dir / " index.html"
201211 )(logger)
@@ -215,8 +225,8 @@ def routes[F[_]: Files: MonadThrow](
215225 refreshRoutes
216226 .combineK(linkedAppWithCaching)
217227 .combineK(proxyRoutes)
218- .combineK(clientSpaRoutes)
219- .combineK(staticAssetRoutes)
228+ .combineK(clientSpaRoutes(ref) )
229+ .combineK(staticAssetRoutes(ref) )
220230 )
221231
222232 clientRoutingPrefix.fold(IO .unit)(s => logger.trace(s " client spa at : $s" )).toResource >>
0 commit comments