@@ -22,6 +22,7 @@ module Servant.Server.Internal
2222 , module Servant.Server.Internal.ServantErr
2323 ) where
2424
25+import Control.Monad.Trans (liftIO)
2526import qualified Data.ByteString as B
2627import qualified Data.ByteString.Char8 as BC8
2728import qualified Data.ByteString.Lazy as BL
@@ -70,7 +71,11 @@ import Servant.Server.Internal.ServantErr
7071class HasServer layout context where
7172 type ServerT layout (m :: * -> *) :: *
7273
73− route :: Proxy layout -> Context context -> Delayed (Server layout) -> Router
74+ route ::
75+ Proxy layout
76+ -> Context context
77+ -> Delayed env (Server layout)
78+ -> Router env
7479
7580type Server layout = ServerT layout Handler
7681
@@ -92,7 +97,7 @@ instance (HasServer a context, HasServer b context) => HasServer (a :<|> b) cont
9297 type ServerT (a :<|> b) m = ServerT a m :<|> ServerT b m
9398
9499 route Proxy context server = choice (route pa context ((\ (a :<|> _) -> a) <$> server))
95− (route pb context ((\ (_ :<|> b) -> b) <$> server))
100+ (route pb context ((\ (_ :<|> b) -> b) <$> server))
96101 where pa = Proxy :: Proxy a
97102 pb = Proxy :: Proxy b
98103
@@ -120,12 +125,12 @@ instance (KnownSymbol capture, FromHttpApiData a, HasServer sublayout context)
120125 a -> ServerT sublayout m
121126
122127 route Proxy context d =
123− DynamicRouter $ \ first ->
128+ CaptureRouter $
124129 route (Proxy :: Proxy sublayout)
125130 context
126− (addCapture d $ case parseUrlPieceMaybe first :: Maybe a of
127− Nothing -> return $ Fail err400
128− Just v -> return $ Route v
131+ (addCapture d $ \ txt -> case parseUrlPieceMaybe txt :: Maybe a of
132+ Nothing -> delayedFail err400
133+ Just v -> return v
129134 )
130135
131136allowedMethodHead :: Method -> Request -> Bool
@@ -144,41 +149,41 @@ processMethodRouter handleA status method headers request = case handleA of
144149 bdy = if allowedMethodHead method request then "" else body
145150 hdrs = (hContentType, cs contentT) : (fromMaybe [] headers)
146151
147−methodCheck :: Method -> Request -> IO (RouteResult ())
152+methodCheck :: Method -> Request -> DelayedIO ()
148153methodCheck method request
149− | allowedMethod method request = return $ Route ()
150− | otherwise = return $ Fail err405
154+ | allowedMethod method request = return ()
155+ | otherwise = delayedFail err405
151156
152−acceptCheck :: (AllMime list) => Proxy list -> B.ByteString -> IO (RouteResult ())
157+acceptCheck :: (AllMime list) => Proxy list -> B.ByteString -> DelayedIO ()
153158acceptCheck proxy accH
154− | canHandleAcceptH proxy (AcceptHeader accH) = return $ Route ()
155− | otherwise = return $ FailFatal err406
159+ | canHandleAcceptH proxy (AcceptHeader accH) = return ()
160+ | otherwise = delayedFailFatal err406
156161
157162methodRouter :: (AllCTRender ctypes a)
158163 => Method -> Proxy ctypes -> Status
159− -> Delayed (Handler a)
160− -> Router
164+ -> Delayed env (Handler a)
165+ -> Router env
161166methodRouter method proxy status action = leafRouter route'
162167 where
163− route' request respond =
168+ route' env request respond =
164169 let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
165170 in runAction (action `addMethodCheck` methodCheck method request
166171 `addAcceptCheck` acceptCheck proxy accH
167− ) respond $ \ output -> do
172+ ) env request respond $ \ output -> do
168173 let handleA = handleAcceptH proxy (AcceptHeader accH) output
169174 processMethodRouter handleA status method Nothing request
170175
171176methodRouterHeaders :: (GetHeaders (Headers h v), AllCTRender ctypes v)
172177 => Method -> Proxy ctypes -> Status
173− -> Delayed (Handler (Headers h v))
174− -> Router
178+ -> Delayed env (Handler (Headers h v))
179+ -> Router env
175180methodRouterHeaders method proxy status action = leafRouter route'
176181 where
177− route' request respond =
182+ route' env request respond =
178183 let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
179184 in runAction (action `addMethodCheck` methodCheck method request
180185 `addAcceptCheck` acceptCheck proxy accH
181− ) respond $ \ output -> do
186+ ) env request respond $ \ output -> do
182187 let headers = getHeaders output
183188 handleA = handleAcceptH proxy (AcceptHeader accH) (getResponse output)
184189 processMethodRouter handleA status method (Just headers) request
@@ -230,8 +235,8 @@ instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)
230235 type ServerT (Header sym a :> sublayout) m =
231236 Maybe a -> ServerT sublayout m
232237
233− route Proxy context subserver = WithRequest $ \ request ->
234− let mheader = parseHeaderMaybe =<< lookup str (requestHeaders request)
238+ route Proxy context subserver =
239+ let mheader req = parseHeaderMaybe =<< lookup str (requestHeaders req)
235240 in route (Proxy :: Proxy sublayout) context (passToServer subserver mheader)
236241 where str = fromString $ symbolVal (Proxy :: Proxy sym)
237242
@@ -262,10 +267,10 @@ instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)
262267 type ServerT (QueryParam sym a :> sublayout) m =
263268 Maybe a -> ServerT sublayout m
264269
265− route Proxy context subserver = WithRequest $ \ request ->
266− let querytext = parseQueryText $ rawQueryString request
267− param =
268− case lookup paramname querytext of
270+ route Proxy context subserver =
271+ let querytext r = parseQueryText $ rawQueryString r
272+ param r =
273+ case lookup paramname (querytext r) of
269274 Nothing -> Nothing -- param absent from the query string
270275 Just Nothing -> Nothing -- param present with no value -> Nothing
271276 Just (Just v) -> parseQueryParamMaybe v -- if present, we try to convert to
@@ -298,13 +303,13 @@ instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)
298303 type ServerT (QueryParams sym a :> sublayout) m =
299304 [a] -> ServerT sublayout m
300305
301− route Proxy context subserver = WithRequest $ \ request ->
302− let querytext = parseQueryText $ rawQueryString request
306+ route Proxy context subserver =
307+ let querytext r = parseQueryText $ rawQueryString r
303308 -- if sym is "foo", we look for query string parameters
304309 -- named "foo" or "foo[]" and call parseQueryParam on the
305310 -- corresponding values
306− parameters = filter looksLikeParam querytext
307− values = mapMaybe (convert . snd) parameters
311+ parameters r = filter looksLikeParam (querytext r)
312+ values r = mapMaybe (convert . snd) (parameters r)
308313 in route (Proxy :: Proxy sublayout) context (passToServer subserver values)
309314 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
310315 looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")
@@ -329,9 +334,9 @@ instance (KnownSymbol sym, HasServer sublayout context)
329334 type ServerT (QueryFlag sym :> sublayout) m =
330335 Bool -> ServerT sublayout m
331336
332− route Proxy context subserver = WithRequest $ \ request ->
333− let querytext = parseQueryText $ rawQueryString request
334− param = case lookup paramname querytext of
337+ route Proxy context subserver =
338+ let querytext r = parseQueryText $ rawQueryString r
339+ param r = case lookup paramname (querytext r) of
335340 Just Nothing -> True -- param is there, with no value
336341 Just (Just v) -> examine v -- param with a value
337342 Nothing -> False -- param not in the query string
@@ -352,8 +357,8 @@ instance HasServer Raw context where
352357
353358 type ServerT Raw m = Application
354359
355− route Proxy _ rawApplication = RawRouter $ \ request respond -> do
356− r <- runDelayed rawApplication
360+ route Proxy _ rawApplication = RawRouter $ \ env request respond -> do
361+ r <- runDelayed rawApplication env request
357362 case r of
358363 Route app -> app request (respond . Route)
359364 Fail a -> respond $ Fail a
@@ -386,10 +391,10 @@ instance ( AllCTUnrender list a, HasServer sublayout context
386391 type ServerT (ReqBody list a :> sublayout) m =
387392 a -> ServerT sublayout m
388393
389− route Proxy context subserver = WithRequest $ \ request ->
390− route (Proxy :: Proxy sublayout) context (addBodyCheck subserver (bodyCheck request))
394+ route Proxy context subserver =
395+ route (Proxy :: Proxy sublayout) context (addBodyCheck subserver bodyCheck)
391396 where
392− bodyCheck request = do
397+ bodyCheck = withRequest $ \ request -> do
393398 -- See HTTP RFC 2616, section 7.2.1
394399 -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
395400 -- See also "W3C Internet Media Type registration, consistency of use"
@@ -397,11 +402,11 @@ instance ( AllCTUnrender list a, HasServer sublayout context
397402 let contentTypeH = fromMaybe "application/octet-stream"
398403 $ lookup hContentType $ requestHeaders request
399404 mrqbody <- handleCTypeH (Proxy :: Proxy list) (cs contentTypeH)
400− <$> lazyRequestBody request
405+ <$> liftIO (lazyRequestBody request)
401406 case mrqbody of
402− Nothing -> return $ FailFatal err415
403− Just (Left e) -> return $ FailFatal err400 { errBody = cs e }
404− Just (Right v) -> return $ Route v
407+ Nothing -> delayedFailFatal err415
408+ Just (Left e) -> delayedFailFatal err400 { errBody = cs e }
409+ Just (Right v) -> return v
405410
406411-- | Make sure the incoming request starts with @"/path"@, strip it and
407412-- pass the rest of the request path to @sublayout@.
@@ -418,28 +423,28 @@ instance (KnownSymbol path, HasServer sublayout context) => HasServer (path :> s
418423instance HasServer api context => HasServer (RemoteHost :> api) context where
419424 type ServerT (RemoteHost :> api) m = SockAddr -> ServerT api m
420425
421− route Proxy context subserver = WithRequest $ \req ->
422− route (Proxy :: Proxy api) context (passToServer subserver $ remoteHost req)
426+ route Proxy context subserver =
427+ route (Proxy :: Proxy api) context (passToServer subserver remoteHost)
423428
424429instance HasServer api context => HasServer (IsSecure :> api) context where
425430 type ServerT (IsSecure :> api) m = IsSecure -> ServerT api m
426431
427− route Proxy context subserver = WithRequest $ \req ->
428− route (Proxy :: Proxy api) context (passToServer subserver $ secure req)
432+ route Proxy context subserver =
433+ route (Proxy :: Proxy api) context (passToServer subserver secure)
429434
430435 where secure req = if isSecure req then Secure else NotSecure
431436
432437instance HasServer api context => HasServer (Vault :> api) context where
433438 type ServerT (Vault :> api) m = Vault -> ServerT api m
434439
435− route Proxy context subserver = WithRequest $ \req ->
436− route (Proxy :: Proxy api) context (passToServer subserver $ vault req)
440+ route Proxy context subserver =
441+ route (Proxy :: Proxy api) context (passToServer subserver vault)
437442
438443instance HasServer api context => HasServer (HttpVersion :> api) context where
439444 type ServerT (HttpVersion :> api) m = HttpVersion -> ServerT api m
440445
441− route Proxy context subserver = WithRequest $ \req ->
442− route (Proxy :: Proxy api) context (passToServer subserver $ httpVersion req)
446+ route Proxy context subserver =
447+ route (Proxy :: Proxy api) context (passToServer subserver httpVersion)
443448
444449-- | Basic Authentication
445450instance ( KnownSymbol realm
@@ -450,12 +455,12 @@ instance ( KnownSymbol realm
450455
451456 type ServerT (BasicAuth realm usr :> api) m = usr -> ServerT api m
452457
453− route Proxy context subserver = WithRequest $ \ request ->
454− route (Proxy :: Proxy api) context (subserver `addAuthCheck` authCheck request)
458+ route Proxy context subserver =
459+ route (Proxy :: Proxy api) context (subserver `addAuthCheck` authCheck)
455460 where
456461 realm = BC8.pack $ symbolVal (Proxy :: Proxy realm)
457462 basicAuthContext = getContextEntry context
458− authCheck req = runBasicAuth req realm basicAuthContext
463+ authCheck = withRequest $ \ req -> runBasicAuth req realm basicAuthContext
459464
460465-- * helpers
461466