我怎样才能捕获Http.Conduit的simpleHttp抛出的404状态异常 [英] How can I catch a 404 status exception thrown by simpleHttp of Http.Conduit

查看:164
本文介绍了我怎样才能捕获Http.Conduit的simpleHttp抛出的404状态异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图下载包含在html文件中的所有png文件。
虽然我很难捕获404状态异常,但是我的程序崩溃了。



以下是一些示例:

  import Network.HTTP.Conduit 
将合格的Data.ByteString.Lazy导入为L

main = do
badUrl =http://www.google.com/intl/zh-CN/images/srpr/WRONG.png
imgData< - (simpleHttp badUrl)`catch` statusExceptionHandler
L.writeFilemy .pngimgData

statusExceptionHandler :: t - > IO L.ByteString
statusExceptionHandler e =(putStrLnoops)>> (返回L.empty)

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

我做错了什么?



更新:

按照Thoma的建议,我将我的代码更改为以下代码片段,并且现在已经有适当的异常处理了。

  main = do 
let badUrl =http://www.google.com/intl/zh_CN/images/srpr/WRONG.png
imgData< - (simpleHttp badUrl)`X.catch` statusExceptionHandler
case xg |的数据x == L.empty - >返回()
|否则 - > L.writeFilemy.pngimgData

statusExceptionHandler :: HttpException - > IO L.ByteString
statusExceptionHandler(StatusCodeException状态标头)=
putStr下载过程中发生错误:
>> (putStrLn $ show status)
>> (return L.empty)


解决方案

您应该阅读关于可扩展异常的Marlow论文。原始的 catch ,由Prelude导出并用于您的代码片段,仅适用于IOError's。 http-conduit代码抛出不同类型的异常, HttpException 。 (有一些动态类型通过Typeable类进行,请参阅文章)。

解决方案是什么?使用 Control.Exception 中的catch和只捕捉你想要处理的错误类型(或者 SomeException )。

  import Network.HTTP.Conduit 
将合格的Data.ByteString.Lazy导入为L
导入Control.Exception作为X

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

statusExceptionHandler :: SomeException - > IO L.ByteString
statusExceptionHandler e =(putStrLnoops)>> (返回L.empty)


I'm trying to download all png files contained in an html file. I have trouble catching 404 status exceptions though, instead my program just crashes.

Here is some sample to demonstrate:

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)

My "oops" message never prints, instead app crashes with:

StatusCodeException (Status {statusCode = 404, statusMessage = "Not Found"}) [("Content-Type","text/html; charset=UTF-8"),("X-Content-Type-Options","nosniff"),("Date","Fri, 27 Jan 2012 03:10:34 GMT"),("Server","sffe"),("Content-Length","964"),("X-XSS-Protection","1; mode=block")]

What am I doing wrong?

Update:

Following Thoma's advice, I changed my code to the following snippet and now have proper exception handling in place.

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)

解决方案

You should probably read the Marlow paper on extensible exceptions. The original catch, exported by Prelude and used in your code snipt, only works for IOError's. The http-conduit code is throwing exceptions of a different type, HttpException to be exact. (there is some dynamic typing going on via the Typeable class, see the paper).

The solution? Use catch from Control.Exception and only catch the error types you want to handle (or SomeException for all of them).

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)

这篇关于我怎样才能捕获Http.Conduit的simpleHttp抛出的404状态异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆