@@ -35,8 +35,7 @@ import Data.Map (Map)
35import qualified Data.Map as Map
35import qualified Data.Map as Map
36import Data.ByteString (ByteString)
36import Data.ByteString (ByteString)
37import qualified Data.ByteString.Char8 as S8
37import qualified Data.ByteString.Char8 as S8
38−import Data.Conduit.Blaze (builderToByteString)
39−import Blaze.ByteString.Builder (flush)
38+import Blaze.ByteString.Builder (toLazyByteString)
40import qualified Blaze.ByteString.Builder as B
39import qualified Blaze.ByteString.Builder as B
41import qualified Data.ByteString.Lazy as L
40import qualified Data.ByteString.Lazy as L
42import qualified Data.ByteString.Lazy.Char8 as L8
41import qualified Data.ByteString.Lazy.Char8 as L8
@@ -45,10 +44,12 @@ import Data.CaseInsensitive (CI)
45import qualified Data.ByteString as S
44import qualified Data.ByteString as S
46import qualified Data.Text as T
45import qualified Data.Text as T
47import qualified Data.Text.Encoding as TE
46import qualified Data.Text.Encoding as TE
48−import qualified Data.Conduit as C
47+import Data.IORef
49−import qualified Data.Conduit.List as CL
48+import Data.Monoid (mempty, mappend)
50+type Session = ReaderT
51+ (Request -> (Response -> IO SResponse) -> IO SResponse)
51−type Session = ReaderT Application (StateT ClientState IO)
52+ (StateT ClientState IO)
53data ClientState = ClientState
54data ClientState = ClientState
54 { _clientCookies :: Map ByteString ByteString
55 { _clientCookies :: Map ByteString ByteString
@@ -96,21 +97,26 @@ setRawPathInfo r rawPinfo =
96srequest :: SRequest -> Session SResponse
97srequest :: SRequest -> Session SResponse
97srequest (SRequest req bod) = do
98srequest (SRequest req bod) = do
98 app <- ask
99 app <- ask
100+ refChunks <- liftIO $ newIORef $ L.toChunks bod
99 let req' = req
101 let req' = req
100− { requestBody = CL.sourceList $ L.toChunks bod
102+ { requestBody = atomicModifyIORef refChunks $ \bss ->
102− liftIO $ app req' >>= runResponse
107+ liftIO $ app req' runResponse
103 -- FIXME cookie processing
108 -- FIXME cookie processing
104 --return sres
109 --return sres
106runResponse :: Response -> IO SResponse
111runResponse :: Response -> IO SResponse
107runResponse res = do
112runResponse res = do
108− bss <- withBody $ \body -> body C.$= CL.map toBuilder C.$= builderToByteString C.$$ CL.consume
113+ refBuilder <- newIORef mempty
114+ let add y = atomicModifyIORef refBuilder $ \x -> (x `mappend` y, ())
115+ withBody $ \body -> body add (return ())
116+ builder <- readIORef refBuilder
109− return $ SResponse s h $ L.fromChunks bss
117+ return $ SResponse s h $ toLazyByteString builder
111− (s, h, withBody) = responseToSource res
119+ (s, h, withBody) = responseToStream res
112− toBuilder (C.Chunk builder) = builder
113− toBuilder C.Flush = flush
115assertBool :: String -> Bool -> Session ()
121assertBool :: String -> Bool -> Session ()
116assertBool s b = unless b $ assertFailure s
122assertBool s b = unless b $ assertFailure s