`wreq`获取/发布异常处理

时间:2016-04-01 16:44:26

标签: haskell

我正在使用@Bean(name = "xmppConnection") public XmppConnectionFactoryBean xmppConnectionFactoryBean() { XmppConnectionFactoryBean connectionFactoryBean = new XmppConnectionFactoryBean(); connectionFactoryBean.setUser(senderId); connectionFactoryBean.setPassword(apiKey); connectionFactoryBean.setConnectionConfiguration(connectionConfiguration()); return connectionFactoryBean; } @Bean(name = "gcmChannel") public MessageChannel messageChannel() { return new DirectChannel(); } @Bean @ServiceActivator(inputChannel = "gcmChannel") public MessageHandler messageHandler() { return new ChatMessageSendingMessageHandler(); } @Autowired @Qualifier("gcmChannel") private MessageChannel messageChannel; 进行一些http调用,并希望捕获任何异常并返回wreq类型。我试过这样的事情,但无法弄清楚如何操纵调用,所以它会打字检查。

Either

我正在粘贴下面的类型错误,但我知道上面的代码无法编译。问题是 -- exhaustive pattern match omitted here safeGetUrl :: URL -> Maybe Login -> Maybe Password -> IO (Either String (Response LBS.ByteString)) safeGetUrl url (Just login) (Just pass) = do let def = defaults opts = def & auth ?~ basicAuth (BS.pack login) (BS.pack pass) r <- getWith opts url `E.catch` handler return $ Right r where handler :: HttpException -> Either String (Response LBS.ByteString) handler (StatusCodeException s _ _) = do return $ Left $ LBS.unpack (s ^. statusMessage) r <- getWith opts url E.catch。第一部分返回handler但异常处理程序返回IO (Res...。我尝试将Either..添加到getWith..中,但也没有输入。

Either

有没有办法捕获此异常并返回Couldn't match type ‘Either String (Response LBS.ByteString)’ with ‘IO (Response LBS.ByteString)’ Expected type: HttpException -> IO (Response LBS.ByteString) Actual type: HttpException -> Either String (Response LBS.ByteString) In the second argument of ‘catch’, namely ‘handler’ In a stmt of a 'do' block: r <- getWith opts url `catch` handler 类型?

2 个答案:

答案 0 :(得分:5)

自@jozefg回答以来,API已经改变了一点,答案就不再编译了。

这是一个编译的更新版本:

import qualified Control.Exception     as E
import           Control.Lens
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Lazy  as LBS
import           Network.HTTP.Client
import           Network.Wreq          as NW

type URL = String

type Login = String

type Password = String

safeGetUrl ::
     URL
  -> Maybe Login
  -> Maybe Password
  -> IO (Either String (Response LBS.ByteString))
safeGetUrl url (Just login) (Just pass) = do
  let def = defaults
      opts = def & auth ?~ basicAuth (BSC.pack login) (BSC.pack pass)
  (Right <$> getWith opts url) `E.catch` handler
  where
    handler :: HttpException -> IO (Either String (Response LBS.ByteString))
    handler (HttpExceptionRequest _ (StatusCodeException r _)) =
      return $ Left $ BSC.unpack (r ^. NW.responseStatus . statusMessage)

答案 1 :(得分:3)

您的问题是句柄的一侧返回一个未包装的响应(无Either),另一侧返回Either - 包装的异常。然后,您尝试将响应包装在Either中,您需要这样做,但它只是在错误的位置。你可以通过切换包装的位置来解决这个问题

safeGetUrl :: URL -> Maybe Login -> Maybe Password -> IO (Either String (Response LBS.ByteString))
 safeGetUrl url (Just login) (Just pass) = do
     let def  = defaults
         opts = def & auth ?~ basicAuth (BS.pack login) (BS.pack pass)
     (Right <$> getWith opts url) `E.catch` handler

   where
     handler :: HttpException -> IO (Either String (Response LBS.ByteString))
     handler (StatusCodeException s _ _) = do
          return $ Left $ LBS.unpack (s ^. statusMessage)

但是,您的功能存在其他一些问题,请记住unpack回复Word8而不是Char。您可能希望导入Data.ByteString.Char,因为其中定义的unpack版本的效果应优于LBS.unpack。没有你的进口虽然我无法确定这一点。我的最终(工作)代码是

import Control.Lens
import Network.Wreq
import Network.HTTP.Client
import qualified Control.Exception as E
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Lazy as LBS

type URL = String
type Login = String
type Password = String

safeGetUrl :: URL
           -> Maybe Login
           -> Maybe Password
           -> IO (Either String (Response LBS.ByteString))
safeGetUrl url (Just login) (Just pass) = do
  let def  = defaults
      opts = def & auth ?~ basicAuth (BSC.pack login) (BSC.pack pass)
  (Right <$> getWith opts url)  `E.catch` handler
  where
    handler :: HttpException -> IO (Either String (Response LBS.ByteString))
    handler (StatusCodeException s _ _) = do
      return $ Left $ BSC.unpack (s ^. statusMessage)