2016-05-07 6 views
0

text/event-streamを使用してHTTP接続でstdinをストリーミングしたいとします。 Network.Wai.EventSourceは良い候補のように見えます。ストリームを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 

:ライン

  • にバイトストリームが1 ServerEventを生成スプリット
  • レイジーバイトストリームとして

    • は、標準入力を読み込みすべての行について(これは間違っていると思われます。おそらく複数のイベントがあるはずです)
    • ビルド私はこれを実行するとIO ServerEvent
    • からWAIアプリケーションがポート1337

    への応用をバインドします(たとえば、 ping -c 5 example.com | stack exec test-exeを使用して)、stdin全体が読み取られるまで応答しません。

    標準入力からを読み込むたびに、HTTP接続をフラッシュするWaiアプリケーションを作成するにはどうすればよいですか?

    答えて

    1

    L.getContentsは単一のIOアクションであるため、1つのイベントのみが作成されます。ここで

    は、複数のイベントが作成され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 
    

    テストするには、1つのウィンドウで、サーバーと別の実行中のコマンドcurl -v http://localhost:1337を起動します。サーバーウィンドウに入力する各行について、カールからデータフレームを取得します。空白行を入力するとHTTP接続は終了しますが、サーバーは実行されたままになり、再度接続することができます。

    関連する問題