Servant Server Sent Events支持

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servant Server Sent Events支持相关的知识,希望对你有一定的参考价值。

如何为服务方定义服务器发送事件(SSE)端点。文档似乎不包括这种情况。

如果Servant不是为实时用例而设计的,哪个Haskell服务器框架支持SSE?

答案

servant使用WAI,您可以随时使用WAI组合器深入了解正常的Raw应用程序和所有库。所以你可以使用Network.Wai.EventSourcewai-extra创建一个Application,这是Raw端点的处理程序类型。就像是:

type MyApi = "normalapi" :> NormalApi 
        :<|> "sse" :> Raw

myServer :: Server MyAPI
myServer = normalServer :<|> eventSourceAppChan myChan
另一答案

是的,我不确定服务器在服务器中发送事件,但更全面的Web框架,如Yesod支持。

看看包装yesod-eventsource

Yesod有一个非常好的食谱,所以你可以在那里找到相当不错的example活动

另一答案

感谢user2141650的答案,我设法获得了使用working example的服务器发送事件的channels

解决方案的要点如下。假设我们有一个只响应消息的echo服务器:

newtype Message = Message { msgText :: Text }

然后我们将定义三个端点,一个用于创建会话,一个用于向会话发送消息,另一个用于使用服务器发送的事件检索会话的消息:

# Create a new session
curl -v -XPOST http://localhost:8081/session/new
# And subscribe to its events
curl -v http://localhost:8081/events/0
# And from another terminal
curl -v -XPOST http://localhost:8081/session/0/echo
     -H "Content-Type: application/json" -d '{"msgText": "Hello"}'

现在让我们看看如何实现端点以将给定会话的消息写入通道:

sendH :: SessionId -> Message -> Handler NoContent
sendH sid msg = do
    -- lookupChannel :: Env -> SessionId -> IO (Maybe (Chan ServerEvent))
    mCh <- liftIO $ lookupChannel env sid
    case mCh of
        Nothing ->
            throwError err404
        Just ch -> do
            liftIO $ writeChan ch (asServerEvent msg)
            return NoContent

Message转换为ServerEvent的函数如下所示:

import           Data.Text.Encoding          as TE
import qualified Data.Text.Lazy              as T

asServerEvent :: Message -> ServerEvent
asServerEvent msg = ServerEvent
    { eventName = Just eName
    , eventId = Nothing
    , eventData = [msg']
    }
    where
      eName :: Builder
      eName = fromByteString "Message arrived"
      msg'  :: Builder
      msg'  = fromByteString $ TE.encodeUtf8 $ T.toStrict $ msgText msg

最后,可以使用evetSourceAppChan实现从服务器检索消息的处理程序,如下所示:

eventsH sid = Tagged $ 
eq respond -> do
    mCh <- lookupChannel env sid
    case mCh of
        Nothing -> do
            let msg = "Could not find session with id: "
                   <> TLE.encodeUtf8 (T.pack (show sid))
            respond $ responseLBS status404 [] msg
        Just ch -> do
            ch' <- dupChan ch
            eventSourceAppChan ch req respond

完整的解决方案可以在我的sanbox上找到。

我希望有所帮助。

以上是关于Servant Server Sent Events支持的主要内容,如果未能解决你的问题,请参考以下文章

轮询、长轮询、server-sent-event

Html5 服务端推送 Server-Sent Event

server-sent event后台用.net怎样实现

Long-Polling, Websockets, SSE(Server-Sent Event) 之间有什么区别?

Akka(43): Http:SSE-Server Sent Event - 服务端主推消息

使用 SSE 发送图像数据