@@ -10,6 +10,7 @@
1010{-# LANGUAGE PolyKinds #-}
1111{-# LANGUAGE RankNTypes #-}
1212{-# LANGUAGE ScopedTypeVariables #-}
13+{-# LANGUAGE TupleSections #-}
1314{-# LANGUAGE TypeFamilies #-}
1415{-# LANGUAGE TypeOperators #-}
1516
@@ -67,8 +68,8 @@ import Servant.API ((:<|>) (..), (:>), BasicAuth, Capt
6768 WithNamedContext,
6869 Description, Summary,
6970 Accept(..),
70− Framing(..), Stream,
71− StreamGenerator(..),
71+ FramingRender(..), Stream,
72+ StreamGenerator(..), ToStreamGenerator(..),
7273 BoundaryStrategy(..))
7374import Servant.API.ContentTypes (AcceptHeader (..),
7475 AllCTRender (..),
@@ -287,40 +288,68 @@ instance OVERLAPPING_
287288 status = toEnum . fromInteger $ natVal (Proxy :: Proxy status)
288289
289290
290−instance ( MimeRender ctype a, ReflectMethod method, Framing framing ctype
291− ) => HasServer (Stream method framing ctype a) context where
291+instance OVERLAPPABLE_
292+ ( MimeRender ctype a, ReflectMethod method,
293+ FramingRender framing ctype, ToStreamGenerator f a
294+ ) => HasServer (Stream method framing ctype (f a)) context where
295+
296+ type ServerT (Stream method framing ctype (f a)) m = m (f a)
297+ hoistServerWithContext _ _ nt s = nt s
298+
299+ route Proxy _ = streamRouter ([],) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
300+ where method = reflectMethod (Proxy :: Proxy method)
301+
302+instance OVERLAPPING_
303+ ( MimeRender ctype a, ReflectMethod method,
304+ FramingRender framing ctype, ToStreamGenerator f a,
305+ GetHeaders (Headers h (f a))
306+ ) => HasServer (Stream method framing ctype (Headers h (f a))) context where
292307
293− type ServerT (Stream method framing ctype a) m = m (StreamGenerator a)
308+ type ServerT (Stream method framing ctype (Headers h (f a))) m = m (Headers h (f a))
294309 hoistServerWithContext _ _ nt s = nt s
295310
296− route Proxy _ action = leafRouter $ \env request respond ->
311+ route Proxy _ = streamRouter (\x -> (getHeaders x, getResponse x)) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
312+ where method = reflectMethod (Proxy :: Proxy method)
313+
314+
315+streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator f a) =>
316+ (b -> ([(HeaderName, B.ByteString)], f a))
317+ -> Method
318+ -> Proxy framing
319+ -> Proxy ctype
320+ -> Delayed env (Handler b)
321+ -> Router env
322+streamRouter splitHeaders method framingproxy ctypeproxy action = leafRouter $ \env request respond ->
297323 let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
298− cmediatype = NHM.matchAccept [contentType (Proxy :: Proxy ctype)] accH
324+ cmediatype = NHM.matchAccept [contentType ctypeproxy] accH
299325 accCheck = when (isNothing cmediatype) $ delayedFail err406
300326 contentHeader = (hContentType, NHM.renderHeader . maybeToList $ cmediatype)
301327 in runAction (action `addMethodCheck` methodCheck method request
302328 `addAcceptCheck` accCheck
303− ) env request respond $ \ (StreamGenerator k) ->
304− Route $ responseStream status200 [contentHeader] $ \write flush -> do
305− write . BB.lazyByteString . header (Proxy :: Proxy framing) $ (Proxy :: Proxy ctype)
306− case boundary (Proxy :: Proxy framing) (Proxy :: Proxy ctype) of
329+ ) env request respond $ \ output ->
330+ let (headers, fa) = splitHeaders output
331+ k = getStreamGenerator . toStreamGenerator $ fa in
332+ Route $ responseStream status200 (contentHeader : headers) $ \write flush -> do
333+ write . BB.lazyByteString $ header framingproxy ctypeproxy
334+ case boundary framingproxy ctypeproxy of
307335 BoundaryStrategyBracket f ->
308− let go x = let bs = mimeRender (Proxy :: Proxy ctype) $ x
336+ let go x = let bs = mimeRender ctypeproxy $ x
309337 (before, after) = f bs
310338 in write ( BB.lazyByteString before
311339 <> BB.lazyByteString bs
312− <> BB.lazyByteString after)
340+ <> BB.lazyByteString after) >> flush
313341 in k go go
314342 BoundaryStrategyIntersperse sep -> k
315343 (\x -> do
316− write . BB.lazyByteString . mimeRender (Proxy :: Proxy ctype) $ x
344+ write . BB.lazyByteString . mimeRender ctypeproxy $ x
317345 flush)
318346 (\x -> do
319− write . (BB.lazyByteString sep <>) . BB.lazyByteString . mimeRender (Proxy :: Proxy ctype) $ x
347+ write . (BB.lazyByteString sep <>) . BB.lazyByteString . mimeRender ctypeproxy $ x
320348 flush)
321− write . BB.lazyByteString . terminate (Proxy :: Proxy framing) $ (Proxy :: Proxy ctype)
322− where method = reflectMethod (Proxy :: Proxy method)
323−
349+ BoundaryStrategyGeneral f ->
350+ let go = (>> flush) . write . BB.lazyByteString . f . mimeRender ctypeproxy
351+ in k go go
352+ write . BB.lazyByteString $ terminate framingproxy ctypeproxy
324353
325354-- | If you use 'Header' in one of the endpoints for your API,
326355-- this automatically requires your server-side handler to be a function