@@ -18,6 +18,7 @@ import Prelude ()
1818import Prelude.Compat
1919
2020import Data.Foldable (toList)
21+import qualified Data.ByteString.Lazy as BL
2122import Data.List (foldl')
2223import Data.Proxy (Proxy (Proxy))
2324import Data.Sequence (fromList)
@@ -29,8 +30,10 @@ import Servant.API ((:<|>) ((:<|>)), (:>),
2930 AuthProtect, BasicAuth,
3031 BasicAuthData,
3132 BuildHeadersTo (..),
33+ BuildFromStream (..),
3234 Capture, CaptureAll,
3335 Description, EmptyAPI,
36+ FramingUnrender (..),
3437 Header, Headers (..),
3538 HttpVersion, IsSecure,
3639 MimeRender (mimeRender),
@@ -40,6 +43,7 @@ import Servant.API ((:<|>) ((:<|>)), (:>),
4043 QueryParams, Raw,
4144 ReflectMethod (..),
4245 RemoteHost, ReqBody,
46+ Stream,
4347 Summary, ToHttpApiData,
4448 Vault, Verb,
4549 WithNamedContext,
@@ -244,6 +248,44 @@ instance OVERLAPPING_
244248 , getHeadersHList = buildHeadersTo . toList $ responseHeaders response
245249 }
246250
251+instance OVERLAPPABLE_
252+ ( RunClient m, MimeUnrender ct a, ReflectMethod method,
253+ FramingUnrender framing a, BuildFromStream a (f a)
254+ ) => HasClient m (Stream method framing ct (f a)) where
255+ type Client m (Stream method framing ct (f a)) = m (f a)
256+ clientWithRoute _pm Proxy req = do
257+ response <- runRequest req
258+ { requestAccept = fromList [contentType (Proxy :: Proxy ct)]
259+ , requestMethod = reflectMethod (Proxy :: Proxy method)
260+ }
261+ return $ decodeFramed (Proxy :: Proxy framing) (Proxy :: Proxy ct) (Proxy :: Proxy a) response
262+
263+instance OVERLAPPING_
264+ ( RunClient m, BuildHeadersTo ls, MimeUnrender ct a, ReflectMethod method,
265+ FramingUnrender framing a, BuildFromStream a (f a)
266+ ) => HasClient m (Stream method framing ct (Headers ls (f a))) where
267+ type Client m (Stream method framing ct (Headers ls (f a))) = m (Headers ls (f a))
268+ clientWithRoute _pm Proxy req = do
269+ response <- runRequest req
270+ { requestAccept = fromList [contentType (Proxy :: Proxy ct)]
271+ , requestMethod = reflectMethod (Proxy :: Proxy method)
272+ }
273+ return Headers { getResponse = decodeFramed (Proxy :: Proxy framing) (Proxy :: Proxy ct) (Proxy :: Proxy a) response
274+ , getHeadersHList = buildHeadersTo . toList $ responseHeaders response
275+ }
276+
277+decodeFramed :: forall ctype strategy a b.
278+ (MimeUnrender ctype a, FramingUnrender strategy a, BuildFromStream a b) =>
279+ Proxy strategy -> Proxy ctype -> Proxy a -> Response -> b
280+decodeFramed framingproxy ctypeproxy typeproxy response =
281+ let (body, uncons) = unrenderFrames framingproxy typeproxy (responseBody response)
282+ loop b | BL.null b = []
283+ | otherwise = case uncons b of
284+ (Right x, r) -> case mimeUnrender ctypeproxy x :: Either String a of
285+ Left err -> Left err : loop r
286+ Right x' -> Right x' : loop r
287+ (Left err, r) -> Left err : loop r
288+ in buildFromStream $ loop body
247289
248290-- | If you use a 'Header' in one of your endpoints in your API,
249291-- the corresponding querying function will automatically take