1 {-# LANGUAGE NoRebindableSyntax #-}
2 {-# OPTIONS_GHC -Wno-type-defaults #-}
4 module Literate.Web.Live.HTTP where
6 -- import Network.Wai.Middleware.Static qualified as Static
7 import Control.Concurrent.STM (STM)
8 import Control.Concurrent.STM qualified as STM
9 import Control.Monad.Classes qualified as MC
10 import Data.ByteString.Lazy qualified as BSL
11 import Data.Function (($))
12 import Data.Map.Strict qualified as Map
13 import Data.Maybe (Maybe (..), fromMaybe)
14 import Data.Semigroup (Semigroup (..))
15 import Data.Text qualified as Text
16 import Data.Text.Lazy qualified as TextL
17 import Data.Text.Lazy.IO qualified as TextL
18 import Literate.Web qualified as Web
19 import Network.HTTP.Types qualified as H
20 import Network.Wai qualified as Wai
22 import System.IO qualified as Sys
24 import Literate.Web.Live.Asset
25 import Literate.Web.Live.Common
30 (model -> m (Map.Map Web.OutputPath (m BSL.ByteString))) ->
31 -- The shim to include in every HTML response
32 Maybe BSL.ByteString ->
34 httpApp modelSTM siteMap mShim req res = do
35 let shim = fromMaybe "" mShim
36 let path = Text.intercalate "/" $ Wai.pathInfo req
37 model <- STM.atomically modelSTM
38 TextL.hPutStrLn Sys.stderr $ "httpApp: GET " <> TextL.fromStrict path
42 ( ["httpApp"] :: [TextL.Text]
43 , ("path", decodeOutputPath path)
44 , ("site" :: TextL.Text, (Map.keys site))
46 case Map.lookup (decodeOutputPath path) site of
48 let s = liveErrorHtmlResponse decodeRouteNothingMsg <> shim
49 res $ Wai.responseLBS H.status404 [(H.hContentType, "text/html")] s
51 content <- MC.exec @IO contentIO
52 res $ Wai.responseLBS H.status200 [(H.hContentType, "text/html")] content
57 logErrorNS "App" $ badRouteEncodingMsg err
58 let s = liveErrorHtmlResponse (badRouteEncodingMsg err) <> shim
59 liftIO $ res $ Wai.responseLBS H.status500 [(H.hContentType, "text/html")] s
61 let s = liveErrorHtmlResponse decodeRouteNothingMsg <> shim
62 liftIO $ res $ Wai.responseLBS H.status404 [(H.hContentType, "text/html")] s
64 renderCatchingErrors val r >>= \case
65 AssetStatic staticPath -> do
66 let mimeType = Static.getMimeType staticPath
67 liftIO $ res $ Wai.responseFile H.status200 [(H.hContentType, mimeType)] staticPath Nothing
68 AssetGenerated Html html -> do
69 let s = html <> toLazy wsClientHtml <> shim
70 liftIO $ res $ Wai.responseLBS H.status200 [(H.hContentType, "text/html")] s
71 AssetGenerated Other s -> do
72 let mimeType = Static.getMimeType $ review (fromPrism_ $ routePrism val) r
73 liftIO $ res $ Wai.responseLBS H.status200 [(H.hContentType, mimeType)] s