开发者

How to Handle Exceptions with http-enumerator

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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜