将http-conduit连接到xml-conduit [英] connecting http-conduit to xml-conduit

查看:140
本文介绍了将http-conduit连接到xml-conduit的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



doPost 我很努力地将http-conduit的响应转换为XML文档。 $ c>函数获取XML文档并将其发布到服务器。服务器响应一个XML文档。

  doPost queryDoc = do 
runResourceT $ do

manager< - liftIO $ newManager def
req< - liftIO $ parseUrl hostname

let req2 = req
{method = H.methodPost
,requestHeaders = [(CI.mk $ fromStringContent-Type,fromStringtext / xml:: Ascii):: Header]
,redirectCount = 0
,checkStatus = \ _ _ - > Nothing
,requestBody = RequestBodyLBS $(renderLBS def queryDoc)
}

res< - http req2 manager
return $ res


$ b

以下工作并返回'200':

  let pingdoc = Document(Prologue [] Nothing [])(ElementSYSTEM[] [])[] 
响应状态标头正文< - doPost pingdoc
return(H.statusCode状态)

但是,当我尝试使用xml-conduit解析Response主体时,遇到问题:

 响应状态标头正文<  -  doPost xmldoc 
let xmlRes'= parseLBS def body

产生的编译错误是:

pre code $>无法匹配预期的类型`L.ByteString'
,其实际类型为'Source m0 ByteString'
在`parseLBS'的第二个参数中,即`body'
在表达式:parseLBS def body
在'xmlRes'方程中:xmlRes'= parseLBS def body

我试过连接使用$ =和$ $$来源于http-conduit到xml-conduit,但我没有任何成功。



有没有人有任何提示指向我在正确的方向?



Neil

解决方案

您可以使用 httpLbs 而不是 http ,所以它会返回一个懒惰的 ByteString 来源 - parseLBS 函数被命名,因为它是这样做的:a L azy b B s t s tring。但是,正如你所提到的那样,最好使用两者直接基于的导管接口。为此,您应该从 doPost 中删除​​ runResourceT 行,并使用以下命令获取XML文档:

  xmlRes'<  -  runResourceT $ do 
响应状态标头正文< - doPost xmldoc
body $ $ sinkDoc def

它使用xml-conduit的 sinkDoc 函数,将来自http-conduit的 Source 连接到xml-conduit的 Sink



连接后,完整的管道必须使用 runResourceT ,这可以确保及时发布所有分配的资源。原始代码的问题在于它太早从 doPost 中运行 ResourceT ;您通常应该使用 runResourceT ,因为流水线必须完全在单个 ResourceT范围内运行。



顺便说一下, res< - http req2 manager;返回$ res 可以简化为 http req2 manager


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 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.

这篇关于将http-conduit连接到xml-conduit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆