Skip to content

Commit dbbe9b7

Browse files
committed
Allow to specify the status of streaming endpoints
1 parent a66aa8a commit dbbe9b7

File tree

3 files changed

+20
-15
lines changed

3 files changed

+20
-15
lines changed

servant-client-core/src/Servant/Client/Core/Internal/HasClient.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,9 @@ instance OVERLAPPING_
285285
instance OVERLAPPABLE_
286286
( RunClient m, MimeUnrender ct a, ReflectMethod method,
287287
FramingUnrender framing a, BuildFromStream a (f a)
288-
) => HasClient m (Stream method framing ct (f a)) where
288+
) => HasClient m (Stream method status framing ct (f a)) where
289289

290-
type Client m (Stream method framing ct (f a)) = m (f a)
290+
type Client m (Stream method status framing ct (f a)) = m (f a)
291291

292292
clientWithRoute _pm Proxy req = do
293293
sresp <- streamingRequest req

servant-server/src/Servant/Server/Internal.hs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,37 +283,40 @@ instance OVERLAPPING_
283283

284284

285285
instance OVERLAPPABLE_
286-
( MimeRender ctype a, ReflectMethod method,
286+
( MimeRender ctype a, ReflectMethod method, KnownNat status,
287287
FramingRender framing ctype, ToStreamGenerator b a
288-
) => HasServer (Stream method framing ctype b) context where
288+
) => HasServer (Stream method status framing ctype b) context where
289289

290-
type ServerT (Stream method framing ctype b) m = m b
290+
type ServerT (Stream method status framing ctype b) m = m b
291291
hoistServerWithContext _ _ nt s = nt s
292292

293-
route Proxy _ = streamRouter ([],) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
293+
route Proxy _ = streamRouter ([],) method status (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
294294
where method = reflectMethod (Proxy :: Proxy method)
295+
status = toEnum . fromInteger $ natVal (Proxy :: Proxy status)
295296

296297
instance OVERLAPPING_
297-
( MimeRender ctype a, ReflectMethod method,
298+
( MimeRender ctype a, ReflectMethod method, KnownNat status,
298299
FramingRender framing ctype, ToStreamGenerator b a,
299300
GetHeaders (Headers h b)
300-
) => HasServer (Stream method framing ctype (Headers h b)) context where
301+
) => HasServer (Stream method status framing ctype (Headers h b)) context where
301302

302-
type ServerT (Stream method framing ctype (Headers h b)) m = m (Headers h b)
303+
type ServerT (Stream method status framing ctype (Headers h b)) m = m (Headers h b)
303304
hoistServerWithContext _ _ nt s = nt s
304305

305-
route Proxy _ = streamRouter (\x -> (getHeaders x, getResponse x)) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
306+
route Proxy _ = streamRouter (\x -> (getHeaders x, getResponse x)) method status (Proxy :: Proxy framing) (Proxy :: Proxy ctype)
306307
where method = reflectMethod (Proxy :: Proxy method)
308+
status = toEnum . fromInteger $ natVal (Proxy :: Proxy status)
307309

308310

309311
streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator b a) =>
310312
(c -> ([(HeaderName, B.ByteString)], b))
311313
-> Method
314+
-> Status
312315
-> Proxy framing
313316
-> Proxy ctype
314317
-> Delayed env (Handler c)
315318
-> Router env
316-
streamRouter splitHeaders method framingproxy ctypeproxy action = leafRouter $ \env request respond ->
319+
streamRouter splitHeaders method status framingproxy ctypeproxy action = leafRouter $ \env request respond ->
317320
let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
318321
cmediatype = NHM.matchAccept [contentType ctypeproxy] accH
319322
accCheck = when (isNothing cmediatype) $ delayedFail err406
@@ -323,7 +326,7 @@ streamRouter splitHeaders method framingproxy ctypeproxy action = leafRouter $ \
323326
) env request respond $ \ output ->
324327
let (headers, fa) = splitHeaders output
325328
k = getStreamGenerator . toStreamGenerator $ fa in
326-
Route $ responseStream status200 (contentHeader : headers) $ \write flush -> do
329+
Route $ responseStream status (contentHeader : headers) $ \write flush -> do
327330
write . BB.lazyByteString $ header framingproxy ctypeproxy
328331
case boundary framingproxy ctypeproxy of
329332
BoundaryStrategyBracket f ->

servant/src/Servant/API/Stream.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,19 @@ import Data.Typeable
2626
(Typeable)
2727
import GHC.Generics
2828
(Generic)
29+
import GHC.TypeLits
30+
(Nat)
2931
import Network.HTTP.Types.Method
3032
(StdMethod (..))
3133
import Text.Read
3234
(readMaybe)
3335

3436
-- | A Stream endpoint for a given method emits a stream of encoded values at a given Content-Type, delimited by a framing strategy. Stream endpoints always return response code 200 on success. Type synonyms are provided for standard methods.
35-
data Stream (method :: k1) (framing :: *) (contentType :: *) (a :: *)
37+
data Stream (method :: k1) (status :: Nat) (framing :: *) (contentType :: *) (a :: *)
3638
deriving (Typeable, Generic)
3739

38-
type StreamGet = Stream 'GET
39-
type StreamPost = Stream 'POST
40+
type StreamGet = Stream 'GET 200
41+
type StreamPost = Stream 'POST 200
4042

4143
-- | Stream endpoints may be implemented as producing a @StreamGenerator@ -- a function that itself takes two emit functions -- the first to be used on the first value the stream emits, and the second to be used on all subsequent values (to allow interspersed framing strategies such as comma separation).
4244
newtype StreamGenerator a = StreamGenerator {getStreamGenerator :: (a -> IO ()) -> (a -> IO ()) -> IO ()}

0 commit comments

Comments
 (0)