@@ -12,8 +12,11 @@ module Network.Wai.Enumerator
12 , toSource
12 , toSource
13 -- ** Handle
13 -- ** Handle
14 , fromHandle
14 , fromHandle
15 -- ** FilePath
16 -- ** FilePath
16 , fromFile
17 , fromFile
17 , fromResponseBody
20 , fromResponseBody
@@ -21,10 +24,12 @@ import Network.Wai (Enumerator (..), Source (..), ResponseBody (..))
21import qualified Network.Wai.Source as Source
24import qualified Network.Wai.Source as Source
22import qualified Data.ByteString.Lazy as L
25import qualified Data.ByteString.Lazy as L
23import qualified Data.ByteString as B
26import qualified Data.ByteString as B
27+import System.Directory (removeFile)
24import System.IO (withBinaryFile, IOMode (ReadMode), Handle, hIsEOF)
28import System.IO (withBinaryFile, IOMode (ReadMode), Handle, hIsEOF)
25import Data.ByteString.Lazy.Internal (defaultChunkSize)
29import Data.ByteString.Lazy.Internal (defaultChunkSize)
26import Control.Concurrent (forkIO)
30import Control.Concurrent (forkIO)
27import Control.Concurrent.MVar
31import Control.Concurrent.MVar
32+import Control.Exception
28import Control.Monad ((<=<))
33import Control.Monad ((<=<))
30-- | Performs a specified conversion on each 'B.ByteString' output by an
35-- | Performs a specified conversion on each 'B.ByteString' output by an
@@ -105,11 +110,27 @@ fromHandle h = Enumerator $ \iter a -> do
105 Left a' -> return $ Left a'
110 Left a' -> return $ Left a'
106 Right a' -> runEnumerator (fromHandle h) iter a'
111 Right a' -> runEnumerator (fromHandle h) iter a'
113+-- | Wrapper around fromHandle to perform an action after EOF or an exception
114+fromHandleFinally :: Handle -> IO a -> Enumerator
115+fromHandleFinally h onEOF = Enumerator $ \iter a0 ->
116+ finally (runEnumerator (fromHandle h) iter a0)
108-- | A little wrapper around 'fromHandle' which first opens a file for reading.
119-- | A little wrapper around 'fromHandle' which first opens a file for reading.
109fromFile :: FilePath -> Enumerator
120fromFile :: FilePath -> Enumerator
110fromFile fp = Enumerator $ \iter a0 -> withBinaryFile fp ReadMode $ \h ->
121fromFile fp = Enumerator $ \iter a0 -> withBinaryFile fp ReadMode $ \h ->
111 runEnumerator (fromHandle h) iter a0
122 runEnumerator (fromHandle h) iter a0
124+-- | Wrapper around fromFile to perform an action after the file is closed.
125+fromFileFinally :: FilePath -> IO a -> Enumerator
126+fromFileFinally fp onClose = Enumerator $ \iter a0 ->
127+ finally (runEnumerator (fromFile fp) iter a0)
130+-- | Enumerator to read and remove a file
131+fromTempFile :: FilePath -> Enumerator
132+fromTempFile fp = fromFileFinally fp $ removeFile fp
113-- | Since the response body is defined as a 'ResponseBody', this function
134-- | Since the response body is defined as a 'ResponseBody', this function
114-- simply reduces the whole value to an enumerator. This can be convenient for
135-- simply reduces the whole value to an enumerator. This can be convenient for
115-- server implementations not optimizing file sending.
136-- server implementations not optimizing file sending.