Подключение 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,

Другие вопросы по тегам