Nei*_*eil 4 haskell conduit http-conduit
我正在努力通过xml-conduit将响应从http-conduit转换为XML文档.
该doPost函数接受XML Document并将其发布到服务器.服务器使用XML文档进行响应.
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
Run Code Online (Sandbox Code Playgroud)
以下工作并返回'200':
let pingdoc = Document (Prologue [] Nothing []) (Element "SYSTEM" [] []) []
Response status headers body <- doPost pingdoc
return (H.statusCode status)
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用xml-conduit解析Response主体时,我遇到了问题:
Response status headers body <- doPost xmldoc
let xmlRes' = parseLBS def body
Run Code Online (Sandbox Code Playgroud)
产生的编译错误是:
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
Run Code Online (Sandbox Code Playgroud)
我尝试使用$ =和$$将源从http-conduit连接到xml-conduit,但我没有任何成功.
有没有人有任何提示指出我正确的方向?提前致谢.
尼尔
你可以使用httpLbs而不是http,因此它返回一个懒惰ByteString而不是一个Source- 该parseLBS函数被命名,因为它是它所需要的:一个L azy B yte S tring.但是,正如您所提到的,最好使用两者直接基于的管道接口.为此,您应该runResourceT从中删除该行doPost,并使用以下内容来获取XML文档:
xmlRes' <- runResourceT $ do
Response status headers body <- doPost xmldoc
body $$ sinkDoc def
Run Code Online (Sandbox Code Playgroud)
这使用xml-conduit的sinkDoc功能,将Sourcehttp-conduit 连接到Sinkxml-conduit.
一旦连接完毕,就必须使用完整的管道runResourceT,这样可以确保及时释放所有分配的资源.原始代码的问题在于它ResourceT从内部运行得太早doPost; 您通常应该runResourceT在想要实际结果的时候使用,因为管道必须完全在单个范围内运行ResourceT.
顺便说一句,res <- http req2 manager; return $ res可以简化为公正http req2 manager.