@@ -64,8 +64,9 @@ module Network.Wai
6464 -- ** Response composers
6565 , responseFile
6666 , responseBuilder
67− , responseSource
6867 , responseLBS
68+ , responseSource
69+ , responseSourceBracket
6970 -- * Response accessors
7071 , responseStatus
7172 , responseHeaders
@@ -74,6 +75,7 @@ module Network.Wai
7475
7576import Blaze.ByteString.Builder (Builder, fromLazyByteString)
7677import Blaze.ByteString.Builder (fromByteString)
78+import Control.Exception (bracket, bracketOnError)
7779import qualified Data.ByteString as B
7880import qualified Data.ByteString.Lazy as L
7981import Data.ByteString.Lazy.Char8 ()
@@ -118,15 +120,36 @@ responseFile = ResponseFile
118120responseBuilder :: H.Status -> H.ResponseHeaders -> Builder -> Response
119121responseBuilder = ResponseBuilder
120122
121−-- | Creating 'Response' from 'C.Source'.
122−responseSource :: H.Status -> H.ResponseHeaders -> C.Source IO (C.Flush Builder) -> Response
123−responseSource st hs src = ResponseSource st hs ($ src)
124−
125123-- | Creating 'Response' from 'L.ByteString'. This is a wrapper for
126124-- 'responseBuilder'.
127125responseLBS :: H.Status -> H.ResponseHeaders -> L.ByteString -> Response
128126responseLBS s h = ResponseBuilder s h . fromLazyByteString
129127
128+-- | Creating 'Response' from 'C.Source'.
129+responseSource :: H.Status -> H.ResponseHeaders -> C.Source IO (C.Flush Builder) -> Response
130+responseSource st hs src = ResponseSource st hs ($ src)
131+
132+-- | Creating 'Response' with allocated resource safely released.
133+--
134+-- * The first argument is an action to allocate resource.
135+--
136+-- * The second argument is a function to release the resource.
137+--
138+-- * The third argument is a function to create
139+-- ('H.Status','H.ResponseHeaders','C.Source' 'IO' ('C.Flush' 'Builder'))
140+-- from the resource.
141+responseSourceBracket :: IO a
142+ -> (a -> IO ())
143+ -> (a -> IO (H.Status
144+ ,H.ResponseHeaders
145+ ,C.Source IO (C.Flush Builder)))
146+ -> IO Response
147+responseSourceBracket setup teardown action =
148+ bracketOnError setup teardown $ \resource -> do
149+ (st,hdr,src) <- action resource
150+ return $ ResponseSource st hdr $ \f ->
151+ bracket (return resource) teardown (\_ -> f src)
152+
130153----------------------------------------------------------------
131154
132155-- | Accessing 'H.Status' in 'Response'.