@@ -35,8 +35,7 @@ import Data.Map (Map)
3535import qualified Data.Map as Map
3636import Data.ByteString (ByteString)
3737import qualified Data.ByteString.Char8 as S8
38−import Data.Conduit.Blaze (builderToByteString)
39−import Blaze.ByteString.Builder (flush)
38+import Blaze.ByteString.Builder (toLazyByteString)
4039import qualified Blaze.ByteString.Builder as B
4140import qualified Data.ByteString.Lazy as L
4241import qualified Data.ByteString.Lazy.Char8 as L8
@@ -45,10 +44,12 @@ import Data.CaseInsensitive (CI)
4544import qualified Data.ByteString as S
4645import qualified Data.Text as T
4746import qualified Data.Text.Encoding as TE
48−import qualified Data.Conduit as C
49−import qualified Data.Conduit.List as CL
47+import Data.IORef
48+import Data.Monoid (mempty, mappend)
5049
51−type Session = ReaderT Application (StateT ClientState IO)
50+type Session = ReaderT
51+ (Request -> (Response -> IO SResponse) -> IO SResponse)
52+ (StateT ClientState IO)
5253
5354data ClientState = ClientState
5455 { _clientCookies :: Map ByteString ByteString
@@ -96,21 +97,26 @@ setRawPathInfo r rawPinfo =
9697srequest :: SRequest -> Session SResponse
9798srequest (SRequest req bod) = do
9899 app <- ask
100+ refChunks <- liftIO $ newIORef $ L.toChunks bod
99101 let req' = req
100− { requestBody = CL.sourceList $ L.toChunks bod
102+ { requestBody = atomicModifyIORef refChunks $ \bss ->
103+ case bss of
104+ [] -> ([], S.empty)
105+ x:y -> (y, x)
101106 }
102− liftIO $ app req' >>= runResponse
107+ liftIO $ app req' runResponse
103108 -- FIXME cookie processing
104109 --return sres
105110
106111runResponse :: Response -> IO SResponse
107112runResponse res = do
108− bss <- withBody $ \body -> body C.$= CL.map toBuilder C.$= builderToByteString C.$$ CL.consume
109− return $ SResponse s h $ L.fromChunks bss
113+ refBuilder <- newIORef mempty
114+ let add y = atomicModifyIORef refBuilder $ \x -> (x `mappend` y, ())
115+ withBody $ \body -> body add (return ())
116+ builder <- readIORef refBuilder
117+ return $ SResponse s h $ toLazyByteString builder
110118 where
111− (s, h, withBody) = responseToSource res
112− toBuilder (C.Chunk builder) = builder
113− toBuilder C.Flush = flush
119+ (s, h, withBody) = responseToStream res
114120
115121assertBool :: String -> Bool -> Session ()
116122assertBool s b = unless b $ assertFailure s