2012-01-27 36 views
6

Tôi đang cố gắng tải xuống tất cả các tệp png có trong tệp html. Tôi gặp sự cố khi bắt ngoại lệ trạng thái 404, thay vào đó chương trình của tôi chỉ bị treo.Làm thế nào tôi có thể bắt ngoại lệ trạng thái 404 được ném bởi simpleHttp của Http.Conduit

Dưới đây là một số mẫu để chứng minh:

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) 

của tôi "oops" tin nhắn không bao giờ in, thay vì ứng dụng bị treo với:

StatusCodeException (Status {statusCode = 404, statusMessage = "Not Found "}) [(" Kiểu nội dung "," văn bản/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 ")]

Tôi đang làm gì sai?

Cập nhật:

Sau lời khuyên Thoma, tôi đã thay đổi mã của tôi đối với đoạn mã sau đây và bây giờ có xử lý ngoại lệ thích hợp tại chỗ.

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) 

Trả lời

6

Có lẽ bạn nên đọc Marlow paper on extensible exceptions. Bản gốc catch, được xuất bởi Prelude và được sử dụng trong đoạn mã của bạn, chỉ hoạt động đối với IOError's. Mã http-conduit đang ném ngoại lệ của một loại khác, HttpException là chính xác. (có một số gõ động đang diễn ra thông qua lớp Typeable, xem bài báo).

Giải pháp? Sử dụng bắt từ Control.Exception và chỉ bắt các loại lỗi bạn muốn xử lý (hoặc SomeException cho tất cả chúng).

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

Cảm ơn bạn đã giải quyết được vấn đề của tôi. Tôi đồng ý chỉ bắt các ngoại lệ cụ thể (đó là bước tiếp theo của tôi, tôi chưa bao giờ đến đó). –

8

Ngoài câu trả lời của Thomas, bạn có thể nói http-conduit không để ném một ngoại lệ bằng cách ghi đè các bản ghi checkStatus loại Request của bạn.

+0

bạn đã thực hiện ngày của tôi, như thường lệ (: –

Các vấn đề liên quan