如何捕获 Http.Conduit 的 simpleHttp 抛出的 404 状态异常
我正在尝试下载 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)
我的“oops”消息永远不会打印,而是应用程序崩溃:
StatusCodeException(状态{statusCode = 404,statusMessage =“未找到”})[(“Content-Type”,“text/html;charset = UTF-8”),(“X-Content-Type-Options” ,"nosniff"),("日期","2012 年 1 月 27 日星期五 03:10:34 GMT"),("服务器","sffe"),("内容长度","964"),("X-XSS-保护","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)
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能应该阅读关于可扩展异常的马洛论文。原始
catch
,由 Prelude 导出并在代码片段中使用,仅适用于 IOError。 http-conduit 代码抛出不同类型的异常,HttpException 。 (通过 Typeable 类进行一些动态类型,请参阅论文)。解决方案是什么?使用 Control.Exception 中的 catch 和只捕获您想要处理的错误类型(或所有错误类型的
SomeException
)。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).除了 Thomas 的回答之外,您还可以通过覆盖
Request
类型的checkStatus
记录来告诉http-conduit
不要抛出异常。In addition to Thomas's answer, you could tell
http-conduit
not to throw an exception by overriding thecheckStatus
record of yourRequest
type.