如何捕获Http.Conduit的simpleHttp抛出的404状态异常

Tho*_*enz 6 haskell http-status-code-404 http-conduit

我正在尝试下载html文件中包含的所有png文件.我很难捕获404状态异常,而我的程序只是崩溃了.

以下是一些示例:

import Network.HTTP.Conduit
import qualified Data.ByteString.Lazy as L

main = do
    let badUrl = "http://www.google.com/intl/en_com/images/srpr/WRONG.png"    
    imgData <- (simpleHttp badUrl) `catch` statusExceptionHandler  
    L.writeFile "my.png" imgData

statusExceptionHandler ::  t -> IO L.ByteString
statusExceptionHandler e = (putStrLn "oops") >> (return L.empty)
Run Code Online (Sandbox Code Playgroud)

我的"oops"消息从不打印,而是应用程序崩溃:

StatusCodeException(Status {statusCode = 404,statusMessage ="Not Found"})[("Content-Type","text/html; charset = UTF-8"),("X-Content-Type-Options","nosniff "),("日期","星期五,2012年1月27日03:10:34 GMT"),("服务器","sffe"),("内容长度","964"),("X-XSS -Protection","1; mode = block")]

我究竟做错了什么?

更新:

根据Thoma的建议,我将代码更改为以下代码段,现在已经适当地处理了异常处理.

main = do
    let badUrl = "http://www.google.com/intl/en_com/images/srpr/WRONG.png"    
    imgData <- (simpleHttp badUrl) `X.catch` statusExceptionHandler  
    case imgData of x | x == L.empty -> return () 
                      | otherwise    -> L.writeFile "my.png" imgData

statusExceptionHandler ::  HttpException -> IO L.ByteString
statusExceptionHandler (StatusCodeException status headers) = 
    putStr "An error occured during download: "
    >> (putStrLn $ show status)
    >> (return L.empty)
Run Code Online (Sandbox Code Playgroud)

Mic*_*man 8

除了托马斯的答案,你可以告诉http-conduit不要通过覆盖checkStatus你的Request类型的记录来抛出异常.


Tho*_*son 7

您应该阅读有关可扩展异常Marlow文章.catch由Prelude导出并在代码片段中使用的原始文件仅适用于IOError.http-conduit代码抛出了不同类型的异常,确切地说是HttpException.(通过Typeable类进行一些动态类型,请参阅文章).

解决方案?使用来自Control.Exception的 catch ,只捕获您想要处理的错误类型(或SomeException所有错误类型).

import Network.HTTP.Conduit
import qualified Data.ByteString.Lazy as L
import Control.Exception as X

main = do
    let badUrl = "http://www.google.com/intl/en_com/images/srpr/WRONG.png"
    imgData <- (simpleHttp badUrl) `X.catch` statusExceptionHandler
        L.writeFile "my.png" imgData

statusExceptionHandler ::  SomeException -> IO L.ByteString
statusExceptionHandler e = (putStrLn "oops") >> (return L.empty)
Run Code Online (Sandbox Code Playgroud)