管道获取Network.Socket.ByteString.recv:失败(未知错误)

时间:2014-12-06 23:24:03

标签: haskell haskell-pipes

也许是一种愚蠢的做事方式,但在这里。我想分割HTTP请求发送/接收来处理响应。

import Pipes
import qualified Pipes.HTTP as HTTP
import Pipes.Core
import qualified Pipes.ByteString as PB
import Network.Socket (withSocketsDo)

fetch m url = do
  req <- lift $ HTTP.parseUrl url
  resp <- lift $ HTTP.withHTTP req m return
  url' <- respond $ HTTP.responseBody resp
  fetch m url'

client :: Client String (Producer PB.ByteString IO ()) IO ()
client = do
          b <- request "http://www.google.com"
          lift $ runEffect $ b >-> PB.stdout

main = withSocketsDo $ HTTP.withManager HTTP.tlsManagerSettings $ \m ->
     runEffect $ fetch m +>> client

似乎合法。但我得到了部分响应打印和“Network.Socket.ByteString.recv:failed(未知错误)”。我需要做些什么不同的事情?

1 个答案:

答案 0 :(得分:3)

错误就是这部分:

HTTP.withHTTP req m return

当一个函数以单词with开头时,你不允许它分配的资源从它所包含的块中逃脱,这是一种约定(不是由类型强制执行)。原因是这些withXXX函数在块完成时处理资源,因此资源在该点之后无效。

所以发生的事情是你尝试return来自withHTTP块的响应,但是通过下一行代码,响应已经被处理掉了。解决方案是使用pipes-safe,它允许您使用Pipes.Safe.bracket在管道内安全地获取资源。您所要做的就是提供一个开放和紧密的行动:

fetch m url = do
    req  <- lift $ HTTP.parseUrl url
    url' <- bracket openSomething closeSomething $ \resp -> do
        respond $ HTTP.responseBody resp
    fetch m url'

这将确保resprespond完成后才会发布。