簡體   English   中英

如何使用Snap框架實現數據流?

[英]How to implement data streaming with the Snap framework?

我想用Snap服務器實現大數據流(雙向)。 為了探索可能性,我創建了一個具有兩個端點的示例程序 - 讀取和寫入。 有一個非常簡單的內部緩沖區,它包含一個ByteString ,寫入端點的任何內容都會出現在讀取端點中。 (目前沒有辦法如何終止流,但這對於此目的來說沒問題。)

{-# LANGUAGE OverloadedStrings #-}                                           
import Control.Applicative                                                   
import Control.Concurrent.MVar.Lifted                                        
import Control.Monad                                                         
import Data.ByteString (ByteString)                                          
import Blaze.ByteString.Builder (Builder, fromByteString)                    
import Data.Enumerator                                                       
import qualified Data.Enumerator.List as E                                   
import Data.Enumerator.Binary (enumFile, iterHandle)                         
import Snap.Core                                                             
import Snap.Http.Server                                                      

main :: IO ()                                                                
main = do                                                                    
  buf <- newEmptyMVar                                                        
  quickHttpServe (site buf)                                                  

site :: MVar ByteString -> Snap ()                                           
site buf =                                                                   
    route [ ("read", modifyResponse (setBufferingMode False                  
                                     . setResponseBody (fromBuf buf)))       
          , ("write", runRequestBody (toBuf buf))                            
          ]                                                                  

fromBuf :: MVar ByteString -> Enumerator Builder IO a                        
fromBuf buf = E.repeatM (liftM fromByteString $ takeMVar buf)                

toBuf :: MVar ByteString -> Iteratee ByteString IO ()                        
toBuf buf = E.mapM_ (putMVar buf)

然后我在不同的終端跑

curl http://localhost:8000/read >/dev/nul

dd if=/dev/zero bs=1M count=100 | \
  curl --data-binary @- http://localhost:8000/write

但寫入部分失敗, 異常轉義為頂層:讀取的字節太多 這顯然是TooManyBytesReadException一個實例,但我無法找到它被拋出的位置。 寫入少量數據(如1MB)可以按預期工作。

我的問題是:

  1. 在哪里/如何修復閱讀限制?
  2. 這會流數據,而不會在內存中加載整個POST請求嗎? 如果沒有,如何解決?

如果您向/write添加不是"application/x-www-form-urlencoded"任何內容類型,它將起作用,例如:

dd if=/dev/zero bs=1M count=100 | \
  curl -H "Content-Type: application/json" --data-binary @- http://localhost:8000/write

該位在快做類似的東西

if contentType == Just "application/x-www-form-urlencoded" then readData maximumPOSTBodySize
  where
    maximumPOSTBodySize = 10*1024*1024

x-www-form-urlencoded是curl的默認值。

要跟進上一個答案:因為application/x-www-form-urlencoded類型application/x-www-form-urlencoded非常常見,因為Snap會為您自動解碼它們並將它們放入請求中的參數映射中。 這個想法在精神上類似於PHP中的$_POST

但是,由於這些映射被讀入RAM,天真地解碼無限量的這些數據將允許攻擊者通過向其發送任意數量的此輸入直到堆耗盡來輕易地對服務器執行DoS操作。 因此, snap-server以這種方式限制了它願意讀取的數據量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM