I'm struggling converting a Response from http-conduit to an XML document via xml-conduit.
The doPost
function takes an XML Document and posts it to the server. The server responds with an XML Document.
doPost queryDoc = do
runResourceT $ do
manager <- liftIO $ newManager def
req <- liftIO $ parseUrl hostname
let req2 = req
{ method = H.methodPost
, requestHeaders = [(CI.mk $ fromString "Content-Type", fromString "text/xml" :: Ascii) :: Header]
, redirectCount = 0
, checkStatus = \_ _ -> Nothing
, requestBody = RequestBodyLBS $ (renderLBS def queryDoc)
}
res <- http req2 manager
return $ res
The following works and returns '200':
let pingdoc = Document (Prologue [] Nothing []) (Element "SYSTEM" [] []) []
Response status headers body <- doPost pingdoc
return (H.statusCode status)
However, when I try and parse the Response body using xml-conduit, I run into problems:
Response status headers body <- doPost xmldoc
let xmlRes' = parseLBS def body
The resulting compilation error is:
Couldn't match expected type `L.ByteString'
with actual type `Source m0 ByteString'
In the second argument of `parseLBS', namely `body'
In the expression: parseLBS def body
In an equation for `xmlRes'': xmlRes' = parseLBS def body
I've tried connecting the Source from http-conduit to the xml-conduit using $= and $$, but I'm not having any success.
Does anyone have any hints to point me in the right direction? Thanks in advance.
Neil
You could use
httpLbs
rather thanhttp
, so that it returns a lazyByteString
rather than aSource
— theparseLBS
function is named because that's what it takes: a Lazy ByteString. However, it's probably best to use the conduit interface that the two are based on directly, as you mentioned. To do this, you should remove therunResourceT
line fromdoPost
, and use the following to get an XML document:This uses xml-conduit's
sinkDoc
function, connecting theSource
from http-conduit to theSink
from xml-conduit.Once they're connected, the complete pipeline has to be run using
runResourceT
, which ensures all allocated resources are released in a timely fashion. The problem with your original code is that it runs theResourceT
too early, from insidedoPost
; you should generally userunResourceT
right at the point that you want an actual result out, because a pipeline has to run entirely within the scope of a singleResourceT
.By the way,
res <- http req2 manager; return $ res
can be simplified to justhttp req2 manager
.