Connect the http channel to the xml channel

I am trying to convert a response from http-conduit to an XML document via an XML feed.

The doPost function accepts an XML document and sends 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 to parse the Response body using xml-conduit, I have problems:

 Response status headers body <- doPost xmldoc let xmlRes' = parseLBS def body 

The resulting compilation error:

 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 tried connecting Source from http-conduit to the xml feed using $ = and $$, but I did not succeed.

Does anyone have any hints to point me in the right direction? Thanks in advance.

Neil

+4
source share
1 answer

You can use httpLbs rather than http so that it returns the lazy ByteString and not Source - the name of the parseLBS function, because this is what you need: a L azy B yte S. However, it is probably best to use the conduit interface, which, as you mentioned, is based directly on. To do this, you must remove the runResourceT line from doPost and use the following to get the XML document:

 xmlRes' <- runResourceT $ do Response status headers body <- doPost xmldoc body $$ sinkDoc def 

This uses the xml-conduit sinkDoc , which connects Source to the http channel with the Sink from the xml channel.

Once they are connected, the full pipeline should be started using runResourceT , which ensures that all allocated resources will be released in a timely fashion. The problem with your source code is that it starts ResourceT too early, from within doPost ; you should usually use runResourceT at the point at which you want the actual result, because the pipeline must fully work within the same ResourceT .

By the way, res <- http req2 manager; return $ res res <- http req2 manager; return $ res can be simplified to a simple http req2 manager .

+6
source

Source: https://habr.com/ru/post/1395988/


All Articles