подключение http-проводника к xml-проводнику - PullRequest
4 голосов
/ 12 февраля 2012

Я изо всех сил пытаюсь преобразовать Ответ из 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 Ответ

6 голосов
/ 12 февраля 2012

Вы можете использовать httpLbs вместо http, чтобы он возвращал ленивый ByteString вместо Source - названа функция parseLBS, потому что это то, что нужно: a L azy B yte S tring. Однако, как вы упомянули, вероятно, лучше всего использовать интерфейс кабелепровода, на котором они основаны. Для этого вы должны удалить строку runResourceT из doPost и использовать следующее для получения XML-документа:

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

Используется функция sinkDoc для xml-проводника, соединяющая Source от http-проводника к Sink от xml-проводника.

После подключения весь конвейер должен быть запущен с использованием runResourceT, что обеспечивает своевременное освобождение всех выделенных ресурсов. Проблема с вашим исходным кодом в том, что он запускает ResourceT слишком рано, изнутри doPost; как правило, вы должны использовать runResourceT прямо в точке, где вы хотите получить фактический результат, потому что конвейер должен работать полностью в пределах одной ResourceT.

Кстати, res <- http req2 manager; return $ res можно упростить до http req2 manager.

...