From 51cce2067d780f6059c660e0cdf63b3f348e2cec Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Tue, 9 Mar 2010 05:20:41 -0500 Subject: [PATCH] Simplify exception handling using MonadCatchIO. Signed-off-by: Anders Kaseorg --- StaticCat.hs | 37 +++++++++++++------------------------ scripts-static-cat.cabal | 3 ++- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/StaticCat.hs b/StaticCat.hs index baa5094..9f8881c 100644 --- a/StaticCat.hs +++ b/StaticCat.hs @@ -1,9 +1,10 @@ {-# LANGUAGE DeriveDataTypeable, ViewPatterns #-} {-# OPTIONS_GHC -O2 -Wall #-} +import Prelude hiding (catch) import Control.Applicative -import Control.Exception import Control.Monad +import Control.Monad.CatchIO import qualified Data.ByteString.Lazy as B import Data.Char import Data.Dynamic @@ -14,7 +15,7 @@ import Network.CGI import Numeric import System.FilePath import System.IO -import System.IO.Error +import System.IO.Error (isDoesNotExistError, isPermissionError) import System.Locale import System.Posix import System.Posix.Handle @@ -67,15 +68,6 @@ types = M.fromList [ (".zip", "application/zip") ] -throwExceptionCGI :: Exception e => e -> CGI a -throwExceptionCGI = throwCGI . toException - -catchExceptionCGI :: Exception e => CGI a -> (e -> CGI a) -> CGI a -a `catchExceptionCGI` handler = - a `catchCGI` \e -> case fromException e of - Nothing -> throwCGI e - Just e_ -> handler e_ - data MyError = NotModified | Forbidden | NotFound | BadMethod | BadRange deriving (Show, Typeable) @@ -98,7 +90,7 @@ checkExtension file = do return $ takeExtension base case M.lookup (map toLower ext') types of - Nothing -> throwExceptionCGI Forbidden + Nothing -> throw Forbidden Just t -> setHeader "Content-Type" t checkMethod :: CGI CGIResult -> CGI CGIResult @@ -108,7 +100,7 @@ checkMethod rOutput = do "HEAD" -> rOutput >> outputNothing "GET" -> rOutput "POST" -> rOutput - _ -> throwExceptionCGI BadMethod + _ -> throw BadMethod httpDate :: String httpDate = "%a, %d %b %Y %H:%M:%S %Z" @@ -123,7 +115,7 @@ checkModified :: EpochTime -> CGI () checkModified mTime = do setHeader "Last-Modified" $ formatHTTPDate mTime (requestHeader "If-Modified-Since" >>=) $ maybe (return ()) $ \ims -> - when (parseHTTPDate ims >= Just mTime) $ throwExceptionCGI NotModified + when (parseHTTPDate ims >= Just mTime) $ throw NotModified checkIfRange :: EpochTime -> CGI (Maybe ()) checkIfRange mTime = do @@ -144,7 +136,7 @@ checkRange mTime size = do (checkIfRange mTime >>=) $ maybe (return Nothing) $ \() -> do case parseRange range size of Just (a, b) | a <= b -> return $ Just (a, b) - _ -> throwExceptionCGI BadRange + _ -> throw BadRange outputAll :: Handle -> FileOffset -> CGI CGIResult outputAll h size = do @@ -164,20 +156,17 @@ outputRange h size (Just (a, b)) = do outputFPS =<< liftIO (B.hGet h (fromIntegral len)) serveFile :: FilePath -> CGI CGIResult -serveFile file = (`catchExceptionCGI` outputMyError) $ do +serveFile file = (`catch` outputMyError) $ do checkExtension file checkMethod $ do let handleOpenError e = - if isDoesNotExistError e then throwExceptionCGI NotFound - else if isPermissionError e then throwExceptionCGI Forbidden - else throwExceptionCGI e - h <- liftIO (openBinaryFile file ReadMode) `catchExceptionCGI` handleOpenError - let handlePostOpenError e = do - liftIO $ hClose h - throwCGI e - (`catchCGI` handlePostOpenError) $ do + if isDoesNotExistError e then throw NotFound + else if isPermissionError e then throw Forbidden + else throw e + h <- liftIO (openBinaryFile file ReadMode) `catch` handleOpenError + (`onException` liftIO (hClose h)) $ do status <- liftIO $ hGetStatus h let mTime = modificationTime status diff --git a/scripts-static-cat.cabal b/scripts-static-cat.cabal index 5c02fe3..734acb2 100644 --- a/scripts-static-cat.cabal +++ b/scripts-static-cat.cabal @@ -13,9 +13,10 @@ Executable static-cat Build-Depends: base >= 4, bytestring, - cgi >= 3001.1.7.2, + cgi >= 3001.1.8, containers, filepath, + MonadCatchIO-mtl, old-locale, time, unix, -- 2.44.0