Подключение http-проводника к xml-проводнику
Я изо всех сил пытаюсь преобразовать Ответ из http-проводника в документ XML через XML-проводник.
doPost
Функция принимает XML-документ и отправляет его на сервер. Сервер отвечает 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
Следующее работает и возвращает '200':
let pingdoc = Document (Prologue [] Nothing []) (Element "SYSTEM" [] []) []
Response status headers body <- doPost pingdoc
return (H.statusCode status)
Однако, когда я пытаюсь проанализировать тело ответа, используя xml-роводник, я сталкиваюсь с проблемами:
Response status headers body <- doPost xmldoc
let xmlRes' = parseLBS def body
Результирующая ошибка компиляции:
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
Я пытался подключить источник с http-проводника к xml-проводнику, используя $= и $$, но у меня ничего не получилось.
У кого-нибудь есть намеки, чтобы указать мне правильное направление? Заранее спасибо.
Нил
1 ответ
Вы могли бы использовать 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
Это использует XML-проводник sinkDoc
функция, соединяющая Source
от http-проводника к Sink
из XML-канала.
После подключения весь конвейер должен быть запущен с использованием runResourceT
, что обеспечивает своевременное освобождение всех выделенных ресурсов. Проблема с вашим исходным кодом в том, что он запускает ResourceT
слишком рано, изнутри doPost
; вы должны обычно использовать runResourceT
прямо в точке, где вы хотите получить фактический результат, потому что конвейер должен работать полностью в рамках одного ResourceT
,
Кстати, res <- http req2 manager; return $ res
можно упростить до http req2 manager
,