@@ -4,6 +4,7 @@ module Payload.Server
44 , start_
55 , startGuarded
66 , startGuarded_
7+ , startGuarded'
78 , Options
89 , defaultOpts
910 , LogLevel (..)
@@ -23,9 +24,9 @@ import Data.String as String
2324import Effect (Effect )
2425import Effect.Aff (Aff )
2526import Effect.Aff as Aff
26- import Effect.Class (liftEffect )
27+ import Effect.Class (class MonadEffect , liftEffect )
2728import Effect.Console (log )
28- import Effect.Exception (Error )
29+ import Effect.Exception (Error , message )
2930import Node.HTTP as HTTP
3031import Node.URL (URL )
3132import Node.URL as Url
@@ -88,7 +89,7 @@ type Logger =
8889-- | Start server with default options, ignoring unexpected startup errors.
8990launch
9091 :: forall routesSpec handlers
91- . Routable routesSpec { } handlers { }
92+ . Routable routesSpec { } handlers { } Aff
9293 => Spec routesSpec
9394 -> handlers
9495 -> Effect Unit
@@ -97,7 +98,7 @@ launch routeSpec handlers = Aff.launchAff_ (start_ routeSpec handlers)
9798-- | Start server with default options and given route spec and handlers (no guards).
9899start_
99100 :: forall routesSpec handlers
100- . Routable routesSpec { } handlers { }
101+ . Routable routesSpec { } handlers { } Aff
101102 => Spec routesSpec
102103 -> handlers
103104 -> Aff (Either String Server )
@@ -106,7 +107,7 @@ start_ = start defaultOpts
106107-- | Start server with given routes and handlers (no guards).
107108start
108109 :: forall routesSpec handlers
109- . Routable routesSpec { } handlers { }
110+ . Routable routesSpec { } handlers { } Aff
110111 => Options
111112 -> Spec routesSpec
112113 -> handlers
@@ -118,7 +119,7 @@ start opts routeSpec handlers = startGuarded opts api { handlers, guards: {} }
118119-- | Start server with default options and given spec, handlers, and guards.
119120startGuarded_
120121 :: forall routesSpec guardsSpec handlers guards
121- . Routable routesSpec guardsSpec handlers guards
122+ . Routable routesSpec guardsSpec handlers guards Aff
122123 => Spec { routes :: routesSpec , guards :: guardsSpec }
123124 -> { handlers :: handlers , guards :: guards }
124125 -> Aff (Either String Server )
@@ -127,25 +128,37 @@ startGuarded_ = startGuarded defaultOpts
127128-- | Start server with given spec, handlers, and guards.
128129startGuarded
129130 :: forall routesSpec guardsSpec handlers guards
130- . Routable routesSpec guardsSpec handlers guards
131+ . Routable routesSpec guardsSpec handlers guards Aff
131132 => Options
132133 -> Spec { guards :: guardsSpec , routes :: routesSpec }
133134 -> { handlers :: handlers , guards :: guards }
134135 -> Aff (Either String Server )
135- startGuarded opts apiSpec api = do
136+ startGuarded = startGuarded' identity
137+
138+ -- | Start server with given monad transformation, spec, handlers, and guards.
139+ startGuarded'
140+ :: forall routesSpec guardsSpec handlers guards m
141+ . MonadEffect m
142+ => Routable routesSpec guardsSpec handlers guards m
143+ => (m ~> Aff )
144+ -> Options
145+ -> Spec { guards :: guardsSpec , routes :: routesSpec }
146+ -> { handlers :: handlers , guards :: guards }
147+ -> Aff (Either String Server )
148+ startGuarded' runM opts apiSpec api = do
136149 let cfg = mkConfig opts
137150 case mkRouter apiSpec api of
138151 Right routerTrie -> do
139- server <- Server <$> (liftEffect $ HTTP .createServer (handleRequest cfg routerTrie))
152+ server <- Server <$> (liftEffect $ HTTP .createServer (handleRequest runM cfg routerTrie))
140153 let httpOpts = Record .delete (Proxy :: Proxy " logLevel" ) opts
141154 listenResult <- listen cfg server httpOpts
142155 pure (const server <$> listenResult)
143156 Left err -> pure (Left err)
144157
145- dumpRoutes :: Trie HandlerEntry -> Effect Unit
158+ dumpRoutes :: forall m . Trie ( HandlerEntry m ) -> Effect Unit
146159dumpRoutes = log <<< showRoutes
147160
148- showRoutes :: Trie HandlerEntry -> String
161+ showRoutes :: forall m . Trie ( HandlerEntry m ) -> String
149162showRoutes routerTrie = Trie .dumpEntries (_.route <$> routerTrie)
150163
151164mkConfig :: Options -> Config
@@ -166,29 +179,54 @@ mkLogger logLevel = { log: log_, logDebug, logError }
166179 logError | logLevel >= LogError = log
167180 logError = const $ pure unit
168181
169- handleRequest :: Config -> Trie HandlerEntry -> HTTP.Request -> HTTP.Response -> Effect Unit
170- handleRequest cfg@{ logger } routerTrie req res = do
182+ handleRequest
183+ :: forall m
184+ . MonadEffect m
185+ => (m ~> Aff )
186+ -> Config
187+ -> Trie (HandlerEntry m )
188+ -> HTTP.Request
189+ -> HTTP.Response
190+ -> Effect Unit
191+ handleRequest runM cfg@{ logger } routerTrie req res = do
171192 let url = Url .parse (HTTP .requestURL req)
172193 logger.logDebug (HTTP .requestMethod req <> " " <> show (url.path))
173194 case requestUrl req of
174- Right reqUrl -> runHandlers cfg routerTrie reqUrl req res
195+ Right reqUrl -> runHandlers runM cfg routerTrie reqUrl req res
175196 Left err -> do
176197 writeResponse res (internalError $ StringBody $ " Path could not be decoded: " <> show err)
177198
178- runHandlers :: Config -> Trie HandlerEntry -> RequestUrl
179- -> HTTP.Request -> HTTP.Response -> Effect Unit
180- runHandlers { logger } routerTrie reqUrl req res = do
181- let (matches :: List HandlerEntry ) = Trie .lookup (reqUrl.method : reqUrl.path) routerTrie
199+ runHandlers
200+ :: forall m
201+ . MonadEffect m
202+ => (m ~> Aff )
203+ -> Config
204+ -> Trie (HandlerEntry m )
205+ -> RequestUrl
206+ -> HTTP.Request
207+ -> HTTP.Response
208+ -> Effect Unit
209+ runHandlers runM { logger } routerTrie reqUrl req res = do
210+ let (matches :: List (HandlerEntry m )) = Trie .lookup (reqUrl.method : reqUrl.path) routerTrie
182211 let matchesStr = String .joinWith " \n " (Array .fromFoldable $ (showRouteUrl <<< _.route) <$> matches)
183212 logger.logDebug $ showUrl reqUrl <> " -> " <> show (List .length matches) <> " matches:\n " <> matchesStr
184- Aff .launchAff_ $ do
185- outcome <- handleNext Nothing matches
186- case outcome of
187- (Forward msg) -> do
188- liftEffect $ writeResponse res (Response .notFound (StringBody " " ))
189- _ -> pure unit
213+ Aff .runAff_
214+ (
215+ case _ of
216+ Left e -> liftEffect do
217+ logger.logError $ message e
218+ writeResponse res (internalError (StringBody " " ))
219+ _ ->
220+ pure unit
221+ )
222+ $ runM do
223+ outcome <- handleNext Nothing matches
224+ case outcome of
225+ (Forward msg) -> do
226+ liftEffect $ writeResponse res (Response .notFound (StringBody " " ))
227+ _ -> pure unit
190228 where
191- handleNext :: Maybe Outcome -> List HandlerEntry -> Aff Outcome
229+ handleNext :: Maybe Outcome -> List ( HandlerEntry m ) -> m Outcome
192230 handleNext Nothing ({ handler } : rest) = do
193231 outcome <- handler reqUrl req res
194232 handleNext (Just outcome) rest
@@ -203,7 +241,7 @@ runHandlers { logger } routerTrie reqUrl req res = do
203241 pure (Forward " No match could handle" )
204242 handleNext _ Nil = pure (Forward " No match could handle" )
205243
206- showMatches :: List HandlerEntry -> String
244+ showMatches :: forall m . List ( HandlerEntry m ) -> String
207245showMatches matches = " " <> String .joinWith " \n " (Array .fromFoldable $ showMatch <$> matches)
208246 where
209247 showMatch = showRouteUrl <<< _.route
0 commit comments