on master help sign in
fromHandleFinally, fromFileFinally, and fromTempFile
dd1b31bMatt Brown
Network/Wai/Enumerator.hs+21
@@ -12,8 +12,11 @@ module Network.Wai.Enumerator
12 , toSource
12 , toSource
13 -- ** Handle
13 -- ** Handle
14 , fromHandle
14 , fromHandle
15+ , fromHandleFinally
15 -- ** FilePath
16 -- ** FilePath
16 , fromFile
17 , fromFile
18+ , fromFileFinally
19+ , fromTempFile
17 , fromResponseBody
20 , fromResponseBody
18 ) where
21 ) where
19
22
@@ -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 ((<=<))
29
34
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'
107
112
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)
117+ onEOF
118+
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
112
123
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)
128+ onClose
129+
130+-- | Enumerator to read and remove a file
131+fromTempFile :: FilePath -> Enumerator
132+fromTempFile fp = fromFileFinally fp $ removeFile fp
133+
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.
wai.cabal+2−1
@@ -18,7 +18,8 @@ Source-repository head
18
18
19Library
19Library
20 Build-Depends: base >= 3 && < 5,
20 Build-Depends: base >= 3 && < 5,
21− bytestring >= 0.9 && < 0.10
21+ bytestring >= 0.9 && < 0.10,
22+ directory
22 Exposed-modules: Network.Wai
23 Exposed-modules: Network.Wai
23 Network.Wai.Enumerator
24 Network.Wai.Enumerator
24 Network.Wai.Source
25 Network.Wai.Source