繁体   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