Как я могу поймать исключение 404 статуса, выдаваемое простой Http.Conduit
Я пытаюсь загрузить все файлы PNG, содержащиеся в HTML-файл. У меня проблемы с перехватом 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)
Мое сообщение "упс" никогда не печатается, вместо этого приложение вылетает с:
StatusCodeException (Status {statusCode = 404, statusMessage = "Not Found"}) [("Content-Type", "text / html; charset = UTF-8"), ("X-Content-Type-Options", "nosniff "), (" Дата "," Пт, 27 января 2012 г. 03:10:34 GMT"),(" Сервер "," sffe "), (" Длина содержимого ","964"),("X-XSS-Защита ","1; режим = блок ")]
Что я делаю неправильно?
Обновить:
Следуя совету Томы, я изменил свой код на следующий фрагмент, и теперь у меня есть правильная обработка исключений.
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)
2 ответа
Возможно, вам следует прочитать статью Марлоу о расширяемых исключениях. Оригинал catch
, экспортируемый Prelude и используемый в вашем фрагменте кода, работает только для IOError. Код http-проводника генерирует исключения другого типа, если быть точным, HttpException. (через класс Typeable происходит некоторая динамическая типизация, см. статью).
Решение? Используйте catch из Control.Exception и поймайте только те типы ошибок, которые вы хотите обработать (или 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)
В дополнение к ответу Томаса, вы могли бы сказать, http-conduit
не выбрасывать исключение, переопределяя checkStatus
запись вашего Request
тип.