@@ -39,8 +39,8 @@ module Network.Wai
3939 ( -- * WAI interface
4040 Request (..)
4141 , Response (..)
42− , ResponseEnumerator
43− , responseEnumerator
42+ , ResponseStream
43+ , responseStream
4444 , Application
4545 , Middleware
4646 , FilePart (..)
@@ -53,11 +53,15 @@ import qualified Data.ByteString.Lazy as L
5353import Data.Typeable (Typeable)
5454import Control.Monad.Trans.Resource (ResourceT)
5555import qualified Data.Conduit as C
56+import qualified Data.Conduit.List as CL
57+import qualified Data.Conduit.Binary as CB
5658import Blaze.ByteString.Builder (Builder, fromLazyByteString)
5759import Network.Socket (SockAddr)
5860import qualified Network.HTTP.Types as H
5961import Data.Text (Text)
6062import Data.ByteString.Lazy.Char8 () -- makes it easier to use responseLBS
63+import Blaze.ByteString.Builder (fromByteString)
64+import Filesystem.Path.CurrentOS (decodeString)
6165
6266-- | Information on the request sent by the client. This abstracts away the
6367-- details of the underlying implementation.
@@ -99,7 +103,7 @@ data Request = Request
99103data Response
100104 = ResponseFile H.Status H.ResponseHeaders FilePath (Maybe FilePart)
101105 | ResponseBuilder H.Status H.ResponseHeaders Builder
102− | ResponseEnumerator (forall a. ResponseEnumerator a)
106+ | ResponseStream (forall a. ResponseStream a)
103107 deriving Typeable
104108
105109data FilePart = FilePart
@@ -131,25 +135,22 @@ data FilePart = FilePart
131135-- A3. You can force blaze-builder to output a ByteString before it is an
132136-- optimal size by sending a flush command.
133137
134−type ResponseEnumerator a =
135− (H.Status -> H.ResponseHeaders -> C.Sink Builder IO a)
138+type ResponseStream a =
139+ (H.Status -> H.ResponseHeaders -> C.SinkM Builder IO a)
136140 -> ResourceT IO a
137141
138−responseEnumerator :: Response -> ResponseEnumerator a
139−responseEnumerator = undefined
140−{-
141−responseEnumerator (ResponseEnumerator e) f = e f
142−responseEnumerator (ResponseFile s h fp mpart) f =
143− run_ $ (maybe enumFile enumFilePart) mpart fp $$ joinI
144− $ EL.map fromByteString $$ f s h
145−responseEnumerator (ResponseBuilder s h b) f = run_ $ do
146− E.yield () $ E.Chunks [b]
147− f s h
148−
149−enumFilePart :: FilePart -> FilePath -> C.Source IO B.ByteString
150−enumFilePart (FilePart offset count) fp =
151− enumFileRange fp (Just offset) (Just count)
152−-}
142+responseStream :: Response -> ResponseStream a
143+responseStream (ResponseStream e) f = e f
144+responseStream (ResponseFile s h fp (Just part)) f =
145+ sourceFilePart part fp C.$$ CL.map fromByteString C.=$ f s h
146+responseStream (ResponseFile s h fp Nothing) f =
147+ CB.sourceFile (decodeString fp) C.$$ CL.map fromByteString C.=$ f s h
148+responseStream (ResponseBuilder s h b) f =
149+ CL.fromList [b] C.$$ f s h
150+
151+sourceFilePart :: FilePart -> FilePath -> C.SourceM IO B.ByteString
152+sourceFilePart (FilePart offset count) fp =
153+ CB.sourceFileRange (decodeString fp) (Just offset) (Just count)
153154
154155responseLBS :: H.Status -> H.ResponseHeaders -> L.ByteString -> Response
155156responseLBS s h = ResponseBuilder s h . fromLazyByteString