Skip to content

Commit 069503e

Browse files
vapourismohasufell
authored andcommitted
Client-side support for server-sent events (SSE)
1 parent 7ef9730 commit 069503e

File tree

9 files changed

+553
-2
lines changed

9 files changed

+553
-2
lines changed

servant-client-core/servant-client-core.cabal

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ library
4141
Servant.Client.Core.Request
4242
Servant.Client.Core.Response
4343
Servant.Client.Core.RunClient
44+
Servant.Client.Core.ServerSentEvents
4445

4546
other-modules:
4647
Servant.Client.Core.Internal
@@ -50,7 +51,8 @@ library
5051
--
5152
-- note: mtl lower bound is so low because of GHC-7.8
5253
build-depends:
53-
base >= 4.9 && < 4.16
54+
attoparsec >= 0.13.2.2 && < 0.15
55+
, base >= 4.9 && < 4.16
5456
, bytestring >= 0.10.8.1 && < 0.12
5557
, constraints >= 0.2 && < 0.14
5658
, containers >= 0.5.7.1 && < 0.7
@@ -94,11 +96,15 @@ test-suite spec
9496
other-modules:
9597
Servant.Client.Core.Internal.BaseUrlSpec
9698
Servant.Client.Core.RequestSpec
99+
Servant.Client.Core.ServerSentEventsSpec
97100

98101
-- Dependencies inherited from the library. No need to specify bounds.
99102
build-depends:
100103
base
101104
, base-compat
105+
, bytestring
106+
, transformers
107+
, servant
102108
, servant-client-core
103109

104110
-- Additional dependencies

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ import Servant.API.Generic
8585
(GenericMode(..), ToServant, ToServantApi
8686
, GenericServant, toServant, fromServant)
8787
import Servant.API.ContentTypes
88-
(contentTypes, AllMime (allMime), AllMimeUnrender (allMimeUnrender))
88+
(contentTypes, AllMime (allMime), AllMimeUnrender (allMimeUnrender), EventStream)
8989
import Servant.API.Status
9090
(statusFromNat)
9191
import Servant.API.TypeLevel (FragmentUnique, AtLeastOneFragment)
@@ -94,13 +94,18 @@ import Servant.API.Modifiers
9494
import Servant.API.TypeErrors
9595
import Servant.API.UVerb
9696
(HasStatus, HasStatuses (Statuses, statuses), UVerb, Union, Unique, inject, statusOf, foldMapUnion, matchUnion)
97+
import Servant.API.ServerSentEvents
98+
(EventKind (JsonEvent, RawEvent), ServerSentEvents')
99+
import Servant.API.Stream
100+
(NoFraming)
97101

98102
import Servant.Client.Core.Auth
99103
import Servant.Client.Core.BasicAuth
100104
import Servant.Client.Core.ClientError
101105
import Servant.Client.Core.Request
102106
import Servant.Client.Core.Response
103107
import Servant.Client.Core.RunClient
108+
import Servant.Client.Core.ServerSentEvents
104109

105110
-- * Accessing APIs as a Client
106111

@@ -462,6 +467,63 @@ instance {-# OVERLAPPING #-}
462467
, requestMethod = reflectMethod (Proxy :: Proxy method)
463468
}
464469

470+
type SseClientDelegate method status =
471+
Stream method status NoFraming EventStream
472+
473+
instance
474+
( RunClient m
475+
, HasClient m (SseClientDelegate method status (EventMessageStreamT IO))
476+
)
477+
=> HasClient m (ServerSentEvents' method status 'RawEvent EventMessage) where
478+
type Client m (ServerSentEvents' method status 'RawEvent EventMessage) =
479+
Client m (SseClientDelegate method status (EventMessageStreamT IO))
480+
481+
hoistClientMonad p _ =
482+
hoistClientMonad
483+
p
484+
(Proxy :: Proxy (SseClientDelegate method status (EventMessageStreamT IO)))
485+
486+
clientWithRoute p _ =
487+
clientWithRoute
488+
p
489+
(Proxy :: Proxy (SseClientDelegate method status (EventMessageStreamT IO)))
490+
491+
instance
492+
( RunClient m
493+
, HasClient m (SseClientDelegate method status (EventStreamT IO))
494+
)
495+
=> HasClient m (ServerSentEvents' method status 'RawEvent (Event a)) where
496+
type Client m (ServerSentEvents' method status 'RawEvent (Event a)) =
497+
Client m (SseClientDelegate method status (EventStreamT IO))
498+
499+
hoistClientMonad p _ =
500+
hoistClientMonad
501+
p
502+
(Proxy :: Proxy (SseClientDelegate method status (EventStreamT IO)))
503+
504+
clientWithRoute p _ =
505+
clientWithRoute
506+
p
507+
(Proxy :: Proxy (SseClientDelegate method status (EventStreamT IO)))
508+
509+
instance
510+
( RunClient m
511+
, HasClient m (SseClientDelegate method status (JsonEventStreamT IO a))
512+
)
513+
=> HasClient m (ServerSentEvents' method status 'JsonEvent a) where
514+
type Client m (ServerSentEvents' method status 'JsonEvent a) =
515+
Client m (SseClientDelegate method status (JsonEventStreamT IO a))
516+
517+
hoistClientMonad p _ =
518+
hoistClientMonad
519+
p
520+
(Proxy :: Proxy (SseClientDelegate method status (JsonEventStreamT IO a)))
521+
522+
clientWithRoute p _ =
523+
clientWithRoute
524+
p
525+
(Proxy :: Proxy (SseClientDelegate method status (JsonEventStreamT IO a)))
526+
465527
-- | If you use a 'Header' in one of your endpoints in your API,
466528
-- the corresponding querying function will automatically take
467529
-- an additional argument of the type specified by your 'Header',

0 commit comments

Comments
 (0)