簡體   English   中英

http管道,快照和惰性IO

[英]http-conduit, snap and lazy IO

我有兩個使用snap框架使用json api的http服務器

我的第一個原型包含一個與此示例處理程序相似的處理程序

import           Data.ByteString (ByteString)
import           Data.ByteString.Char8 as B (unwords, putStrLn)
import           Data.ByteString.Lazy.Char8 as L (putStrLn)
import           Control.Monad.IO.Class (liftIO)
import           Data.Monoid ((<>))
import           Snap.Core (getParam, modifyResponse, setHeader, writeLBS) 
import           Network.HTTP.Conduit
import           Network.HTTP.Client (defaultManagerSettings)


exampleHandler :: AppHandler ()
exampleHandler = do resp <- liftIO
                         $ do L.putStrLn "Begin request ..."
                              initReq <- parseUrl "http://localhost:8001/api"
                              manager <- newManager defaultManagerSettings
                              let req  = initReq { method = "GET"
                                                 , proxy = Nothing}
                              r <- httpLbs req manager
                              L.putStrLn "... finished request."
                              return $ responseBody r
                    liftIO . L.putStrLn $ "resp: " <> resp
                    modifyResponse $ setHeader "Content-Type" "application/json"
                    writeLBS $ "{ \"data\": \""<> resp <>"\" }"

如果我發出ajax請求,則發送和接收響應-當服務器在控制台上寫入resp: testdata時,我會看到此消息,但使用writeLBS發送給瀏覽器的響應卻沒有。 現在,如果我將最后一行更改為

                    writeLBS $ "{ \"data\": \""<> "something fixed" <>"\" }"

一切都像魅力。 我認為我正在遇到惰性IO的陷阱之一,但是我不知道該如何解決。

我還嘗試了一些不帶liftIO變體,但將liftIO放在必要的地方。

編輯

根據@MichaelSnoyman的評論,我對writeLBS進行了一些研究,並試圖

               modifyResponse $ setBufferingMode False
                              . setHeader "Content-Type" "application/json"
               writeLBS resp

正如我認為緩沖可能是問題-不,不是

此外,我嘗試顯式編寫一個setResponseBody

               let bb = enumBuilder . fromLazyByteString $ "{ \"data\": \""<> resp <>"\" }"
               modifyResponse $ setBufferingMode False
                              . setHeader "Content-Type" "application/json"
                              . setResponseBody bb

這也顯示沒有成功。

我已經解決了這個問題-實際上,這是javascript獲取手寫json的問題(自我注意:永遠不要再這樣做了)。 在輸入數據的末尾有一個不間斷的空格,該空格未正確編碼,而且由於我是JS的新手,所以我沒有從錯誤消息中得到該空格。

中間解決方案是添加urlEncode並制作一個嚴格的ByteString

               let respB = urlEncode . L.toStrict $ C.responseBody resp
               modifyResponse $ setBufferingMode False
                              . setHeader "Content-Type" "application/json"
               writeBS $ "{ \"data\": \"" <> respB <> "\" }"

當然,您必須相應地更改進口。

長期的解決方案是:編寫一個正確的from/toJSON實例,然后讓該庫處理。

暫無
暫無

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

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