2012-01-27 4 views
6

'un Http: tarafından atılan 404 durum özel durumunu nasıl yakalayabilirim? Bir html dosyasında bulunan tüm png dosyalarını indirmeye çalışıyorum. 404 durum istisnalarını yakalamakta zorlanıyorum, bunun yerine programım çöküyor.Http.Conduit

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 "hata" mesajı asla baskılar, yerine uygulama kilitleniyor ile: Burada

bazı örnek göstermektir

StatusCodeException (Status {statusCode = 404, StatusMessage = "Not Found "}) [(" İçerik Türü "," text/html; charset = UTF-8 "), (" X-Content-Type-Options "," nosniff "), (" Tarih "," Cum, 27 Ocak) 2012 03:10:34 GMT "), (" Sunucu "," sffe "), (" İçerik Uzunluğu "," 964 "), (" X-XSS Koruması "," 1; mod = blok ")]

Neyi yanlış yapıyorum?

Güncelleme

: Thoma tavsiyelerine uyarak

, şu pasajı için kodumu değiştirdi ve şimdi yerinde uygun durum işleme sahiptir.

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) 

cevap

6

Muhtemelen Marlow paper on extensible exceptions okumalısınız. Prelude tarafından dışa aktarılan ve kod snipt'inizde kullanılan orijinal catch, yalnızca IOError'lar için çalışır. Http-conduit kodu, tam olarak HttpException farklı türde istisnalar atıyor. (Typeable sınıfı üzerinden devam eden bazı dinamik yazmalar var, kağıda bakın).

Çözüm? Yakalamayı Control.Exception'dan kullanın ve yalnızca işlemek istediğiniz hata türlerini yakalayın (ya da tümü için 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) 
+0

Teşekkürler, bu benim problemimi çözdü. Sadece özel istisnaları yakalamaya katılıyorum (bu benim bir sonraki adımdı, hiç bulamadım). –

8

Thomas'ın cevap ek olarak, size Request Çeşidi checkStatus kaydını geçersiz kılarak bir istisna değil http-conduit söyleyebilirdi.

+0

günümü her zamanki gibi yaptın (: –