我想使用text/event-stream
通过HTTP连接传输stdin。 Network.Wai.EventSource看起来像是一个很好的候选人。
我尝试使用此代码:
import Network.Wai
import Network.Wai.EventSource
import Network.Wai.Middleware.AddHeaders
import Network.Wai.Handler.Warp (run)
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as C
import Blaze.ByteString.Builder.ByteString
toEvent :: [L.ByteString] -> ServerEvent
toEvent s = ServerEvent {
eventName = Nothing,
eventId = Nothing,
eventData = map fromLazyByteString s
}
createWaiApp :: IO L.ByteString -> Application
createWaiApp input = eventSourceAppIO $ fmap (toEvent . C.lines) input
main :: IO ()
main = run 1337 $ createWaiApp L.getContents
我认为:
IO ServerEvent
当我运行它时(例如使用ping -c 5 example.com | stack exec test-exe
),直到读完整个stdin才会响应。
如何构建一个Wai应用程序,每次从stdin读取行时都会刷新HTTP连接?
答案 0 :(得分:1)
L.getContents
是一个单独的IO操作,因此只会创建一个事件。
以下是eventSourcEventAppIO的示例,其中创建了多个事件:
import Blaze.ByteString.Builder.Char8 (fromString)
...same imports as above...
nextEvent :: IO ServerEvent
nextEvent = do
s <- getLine
let event = if s == ""
then CloseEvent
else ServerEvent
{ eventName = Nothing
, eventId = Nothing
, eventData = [ fromString s ]
}
case event of
CloseEvent -> putStrLn "<close event>"
ServerEvent _ _ _ -> putStrLn "<server event>"
return event
main :: IO ()
main = run 1337 $ eventSourceAppIO nextEvent
要测试,请在一个窗口中启动服务器,然后在另一个窗口中运行命令curl -v http://localhost:1337
。对于您在服务器窗口中输入的每一行,您将从curl获得一个数据框。输入一个空行将关闭HTTP连接,但服务器将继续运行,允许您再次连接到它。