Haskell newbie here. I'm attempting to use the http-enumerator to query a service via XML over HTTP. I'm able to connect and send an xml-formatted request, and to receive the xml-formatted response.
When the query is successful, the server sends back a response starting with
What I'm struggling with is the correct way to handle the exceptions indicated in the FAULT document. I'm trying to use Either
, but without success.
What I have below compiles in ghci:
import Network.HTTP.Enumerator
import Network.HTTP.Types
import qualified Data.ByteString.Lazy as L
import Data.ByteString.UTF8
import Text.XML.Light
hostname = "https://server..."
doPost username password token = do
let q = QName "SYSTEM" Nothing Nothing
let attribs = [Attr {attrKey = QName "user" Nothing Nothing, attrVal = username},
Attr {attrKey = QName "password" Nothing Nothing, attrVal = password},
Attr {attrKey = QName "token" Nothing Nothing, attrVal = token}]
let doc = Element {elName=q, elAttribs=attribs, elContent= [], elLine=Nothing}
req0 <- parseUrl hostname
let req = req0 { method = methodPost
, requestHeaders = [("Content-Type", "text/xml")]
, requestBody = RequestBodyBS $ fromString $ showTopElement doc
}
res <- withManager $ httpLbs req
let status = Network.HTTP.Enumerator.statusCode res
let content = responseBody res
-- this is where I would check for different fault codes using a case statement
if content == "<FAULT/>"
then Left "error"
else Right content
However, when I attempt to run it in ghci I get the following:
*Main> doPost "user" "password" ""
<interactive>:1:1:
No instances for (Control.Failure.Failure
开发者_如何学C HttpException (Either a0),
Control.Monad.IO.Control.MonadControlIO (Either a0))
arising from a use of `doPost'
Possible fix:
add instance declarations for
(Control.Failure.Failure HttpException (Either a0),
Control.Monad.IO.Control.MonadControlIO (Either a0))
In the expression: doPost "user" "password" ""
In an equation for `it': it = doPost "user" "password" ""
What is the best way to handle exceptions in a case like this?
Thanks in advance. Neil
You need to put a "return $" before the last if. parseUrl needs to run in a monad which is an instance of Failure HttpException
, such as IO or Maybe. withManager
needs a monad which is an instance of MonadControlIO
, such as IO
.
Currently, your if
at the end is forcing the entire do
-block to run in the Either String
monad, which is why you're getting the "no instance" exceptions. If you add a return, your final result will be something like IO (Either String XML)
.
精彩评论