Sassa NF
Sassa NF

Reputation: 5406

Pipes get Network.Socket.ByteString.recv: failed (Unknown error)

Maybe a silly way to do things, but here it goes. I wanted to split the HTTP request send/receive from processing the response.

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

Seems legitimate. But I get part of response printed and "Network.Socket.ByteString.recv: failed (Unknown error)". What do I need to do differently?

Upvotes: 1

Views: 211

Answers (1)

Gabriella Gonzalez
Gabriella Gonzalez

Reputation: 35099

The error is this part:

HTTP.withHTTP req m return

There is a convention (not enforced by the types) that when a function begins with the word with that you are not allowed to let the resource it allocates escape from the block it encloses. The reason why is that these withXXX functions dispose of the resource when the block completes, so the resource is invalid past that point.

So what happened is that you tried to return the response from the withHTTP block, but by the next line of code the response has already been disposed of. The solution is to use pipes-safe, which allows you to acquire resources safely within a pipe using Pipes.Safe.bracket. All you have to do is provide an open and close action:

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

That will ensure that resp is not released until after the respond completes.

Upvotes: 3

Related Questions