Haskell HTTP client using ByteString

504 Views Asked by At

I'm doing some HTTP Requests and I want to get the corresponding Responses as ByteString instead of String. I'm using HTTP-4000.2.18.

As far as I can tell, this is precisely what BufferType is for:

to give the user freedom in how request and response content is represented

However, I'm at a loss on how to make it work. Here's what I have so far: I'm constructing requests using a function called getLazyRequest as follows:

getLazyRequest
    :: String                   -- ^URL to fetch
    -> Request Lazy.ByteString  -- ^The constructed request

and then I should be able to pass the requests directly to simpleHTTP. The getLazyRequest function is identical with getRequest except it returns a request with type ByteString instead of String. But it doesn't work..

Complete source:

import Network.HTTP
import Network.URI ( parseURI )
import qualified Data.ByteString.Lazy as Lazy
import Network.BufferType ( BufferOp(..), BufferType(..) )


main = do
    let req = getLazyRequest "http://hackage.haskell.org/"
    rsp <- simpleHTTP req
    line <- fmap (take 100) (getResponseBody rsp)
    putStrLn ""


getLazyRequest
    :: String                   -- ^URL to fetch
    -> Request Lazy.ByteString  -- ^The constructed request
getLazyRequest urlString =
  case parseURI urlString of
    Nothing -> error ("getLazyRequest: Not a valid URL - " ++ urlString)
    Just u  -> mkRequest GET u

The errors:

No instance for (HStream Lazy.ByteString)
  arising from a use of `simpleHTTP'
Possible fix:
  add an instance declaration for (HStream Lazy.ByteString)
In a stmt of a 'do' block: rsp <- simpleHTTP req

No instance for (BufferType Lazy.ByteString)
  arising from a use of `mkRequest'
Possible fix:
  add an instance declaration for (BufferType Lazy.ByteString)
In the expression: mkRequest GET u
In a case alternative: Just u -> mkRequest GET u

I don't understand why these errors, since Lazy.ByteString is an instance both of HStream and BufferType.

EDIT

Indeed, I have to versions of bytestring installed. Is it possible that I installed one of them using sudo and the other using my user?

$ ghc-pkg list bytestring
/var/lib/ghc/package.conf.d
   bytestring-0.9.2.1
/home/adizere/.ghc/x86_64-linux-7.4.1/package.conf.d
   bytestring-0.10.4.1

I couldn't unregister any of these two versions, so instead I cabalized the code and it seems to work now.

2

There are 2 best solutions below

0
On BEST ANSWER

Since @user5402 confirmed that your code is correct (modulo take vs Lazy.take), then I'm almost sure you have multiple versions of bytestring package installed. E.g. you are importing one version, but HTTP is compiled against other one.

Check ghc-pkg list bytestring and unregister/hide one unnecessary version.

Or, better, cabalize your code and/or use cabal sandbox.

See also: Acid-state: MonadState instance for Update and https://ghc.haskell.org/trac/ghc/ticket/8278#comment:2

0
On

Change:

    line <- fmap (take 100) (getResponseBody rsp)

to:

    line <- fmap (Lazy.take 100) (getResponseBody rsp)

Your code type-checks on my system with this change.