@@ -9,6 +9,7 @@ import Control.Lens ((^?), _Just, _Right)
9import qualified Data.Attoparsec.ByteString.Char8 as A
9import qualified Data.Attoparsec.ByteString.Char8 as A
10import Data.ByteString (ByteString)
10import Data.ByteString (ByteString)
11import qualified Data.ByteString.Char8 as BSC
11import qualified Data.ByteString.Char8 as BSC
12+import qualified Data.ByteString.Lazy.Char8 as BSLC
12import Data.List (uncons)
13import Data.List (uncons)
13import Data.Maybe
14import Data.Maybe
14import Data.Semigroup ((<>))
15import Data.Semigroup ((<>))
@@ -18,10 +19,13 @@ import Language.Javascript.JSaddle.Run (syncPoint)
18import Language.Javascript.JSaddle.WebSockets
19import Language.Javascript.JSaddle.WebSockets
19import Network.HTTP.Client (Manager, defaultManagerSettings, newManager)
20import Network.HTTP.Client (Manager, defaultManagerSettings, newManager)
20import qualified Network.HTTP.ReverseProxy as RP
21import qualified Network.HTTP.ReverseProxy as RP
22+import qualified Network.HTTP.Types as H
21import Network.Socket
23import Network.Socket
22import Network.Wai (Application)
24import Network.Wai (Application)
25+import qualified Network.Wai as W
23import Network.Wai.Handler.Warp
26import Network.Wai.Handler.Warp
24import Network.Wai.Handler.Warp.Internal (settingsHost, settingsPort)
27import Network.Wai.Handler.Warp.Internal (settingsHost, settingsPort)
28+import Network.WebSockets (ConnectionOptions)
25import Network.WebSockets.Connection (defaultConnectionOptions)
29import Network.WebSockets.Connection (defaultConnectionOptions)
26import Obelisk.ExecutableConfig (get)
30import Obelisk.ExecutableConfig (get)
27import Reflex.Dom.Core
31import Reflex.Dom.Core
@@ -34,7 +38,7 @@ import Text.URI.Lens
35run :: Int -- ^ Port to run the backend
39run :: Int -- ^ Port to run the backend
36 -> IO () -- ^ Backend
40 -> IO () -- ^ Backend
37− -> (Widget () (), Widget () ()) -- ^ Frontend widget (head, body)
41+ -> (StaticWidget () (), Widget () ()) -- ^ Frontend widget (head, body)
39run port backend frontend = do
43run port backend frontend = do
40 let handleBackendErr (_ :: SomeException) = hPutStrLn stderr "backend stopped; make a change to your code to reload"
44 let handleBackendErr (_ :: SomeException) = hPutStrLn stderr "backend stopped; make a change to your code to reload"
@@ -52,7 +56,7 @@ getConfigRoute = do
52defAppUri :: URI
56defAppUri :: URI
53defAppUri = fromMaybe (error "defAppUri") $ URI.mkURI "http://127.0.0.1:8000"
57defAppUri = fromMaybe (error "defAppUri") $ URI.mkURI "http://127.0.0.1:8000"
55−runWidget :: RunConfig -> (Widget () (), Widget () ()) -> IO ()
59+runWidget :: RunConfig -> (StaticWidget () (), Widget () ()) -> IO ()
56runWidget conf (h, b) = do
60runWidget conf (h, b) = do
57 uri <- fromMaybe defAppUri <$> getConfigRoute
61 uri <- fromMaybe defAppUri <$> getConfigRoute
58 let port = fromIntegral $ fromMaybe 80 $ uri ^? uriAuthority . _Right . authPort . _Just
62 let port = fromIntegral $ fromMaybe 80 $ uri ^? uriAuthority . _Right . authPort . _Just
@@ -66,12 +70,26 @@ runWidget conf (h, b) = do
67 (\skt -> do
71 (\skt -> do
68 man <- newManager defaultManagerSettings
72 man <- newManager defaultManagerSettings
69− app <- jsaddleWithAppOr
70− defaultConnectionOptions
71− (mainWidgetWithHead' (const h, const b) >> syncPoint)
72− (fallbackProxy redirectHost redirectPort man)
73+ app <- obeliskApp defaultConnectionOptions h b (fallbackProxy redirectHost redirectPort man)
73 runSettingsSocket settings skt app)
74 runSettingsSocket settings skt app)
76+obeliskApp :: ConnectionOptions -> StaticWidget () () -> Widget () () -> Application -> IO Application
77+obeliskApp opts h b backend = do
78+ html <- BSLC.fromStrict <$> indexHtml h
79+ let entryPoint = mainWidget' b >> syncPoint
80+ jsaddleOr opts entryPoint $ \req sendResponse -> case (W.requestMethod req, W.pathInfo req) of
81+ ("GET", []) -> sendResponse $ W.responseLBS H.status200 [("Content-Type", "text/html")] html
82+ ("GET", ["jsaddle.js"]) -> sendResponse $ W.responseLBS H.status200 [("Content-Type", "application/javascript")] $ jsaddleJs False
83+ _ -> backend req sendResponse
85+indexHtml :: StaticWidget () () -> IO ByteString
87+ ((), bs) <- renderStatic $ el "html" $ do
89+ el "body" $ return ()
90+ elAttr "script" ("src" =: "/jsaddle.js") $ return ()
91+ return $ "<!DOCTYPE html>" <> bs
75-- | like 'bindPortTCP' but reconnects on exception
93-- | like 'bindPortTCP' but reconnects on exception
76bindPortTCPRetry :: Settings
94bindPortTCPRetry :: Settings
77 -> (IOError -> IO ()) -- ^ Action to run the first time an exception is caught
95 -> (IOError -> IO ()) -- ^ Action to run the first time an exception is caught