connecting http-conduit to xml-conduit

蓝咒 提交于 2020-01-13 11:02:41

问题


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


回答1:


You could use httpLbs rather than http, so that it returns a lazy ByteString rather than a Source — the parseLBS 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 the runResourceT line from doPost, and use the following to get an XML document:

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

This uses xml-conduit's sinkDoc function, connecting the Source from http-conduit to the Sink 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 the ResourceT too early, from inside doPost; you should generally use runResourceT right at the point that you want an actual result out, because a pipeline has to run entirely within the scope of a single ResourceT.

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



来源:https://stackoverflow.com/questions/9245342/connecting-http-conduit-to-xml-conduit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!