This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "snap-server".

The branch, master has been updated
       via  ffc57c6a7f1d5dc82fee303d99a3dda3188e2402 (commit)
      from  775935eb4a1065a7c4ed32a3d8ae6118dfd3219c (commit)


Summary of changes:
 src/Snap/Internal/Http/Parser.hs              |   18 ++---
 src/Snap/Internal/Http/Server.hs              |   49 ++++++++-----
 test/suite/Snap/Internal/Http/Parser/Tests.hs |   94 +++++++++++++------------
 test/testserver/Main.hs                       |    9 ++-
 4 files changed, 95 insertions(+), 75 deletions(-)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ffc57c6a7f1d5dc82fee303d99a3dda3188e2402
Author: Gregory Collins <[email protected]>
Date:   Fri Sep 3 16:56:06 2010 -0400

    Rework iteratee code inside the server to make unsafeDetachRequestBody work 
properly

diff --git a/src/Snap/Internal/Http/Parser.hs b/src/Snap/Internal/Http/Parser.hs
index 2b5f588..4eb4810 100644
--- a/src/Snap/Internal/Http/Parser.hs
+++ b/src/Snap/Internal/Http/Parser.hs
@@ -45,7 +45,8 @@ import             Prelude hiding (take, takeWhile)
 ------------------------------------------------------------------------------
 import             Snap.Internal.Http.Types hiding (Enumerator)
 import             Snap.Iteratee hiding (take, foldl', filter)
-
+import qualified   Snap.Iteratee as I
+import             Snap.Internal.Iteratee.Debug
 
 
 ------------------------------------------------------------------------------
@@ -118,14 +119,9 @@ toHex n' = s
 -- > Chunk "a\r\nfoobarquux\r\n0\r\n\r\n" Empty
 --
 writeChunkedTransferEncoding :: Enumerator IO a
-                             -> Enumerator IO a
-writeChunkedTransferEncoding enum it = do
+writeChunkedTransferEncoding it = do
     let out = wrap it
-    i   <- enum out
-    v   <- runIter i (EOF Nothing)
-    j   <- checkIfDone return v
-    w   <- runIter j (Chunk (WrapBS "0\r\n\r\n"))
-    checkIfDone return w
+    return out
 
   where
     ignoreEOF iter = IterateeG $ \s ->
@@ -135,7 +131,8 @@ writeChunkedTransferEncoding enum it = do
               i <- runIter iter s >>= checkIfDone return
               return $ Cont (ignoreEOF i) Nothing
 
-    wrap iter = bufIt (0,D.empty) $ ignoreEOF iter
+    --wrap iter = bufIt (0,D.empty) $ ignoreEOF iter
+    wrap iter = bufIt (0,D.empty) iter
 
     bufSiz = 16284
 
@@ -162,7 +159,8 @@ writeChunkedTransferEncoding enum it = do
         case s of
           (EOF Nothing) -> do
                i'  <- sendOut dl iter
-               runIter i' (EOF Nothing)
+               j   <- liftM liftI $ runIter i' (Chunk (WrapBS "0\r\n\r\n"))
+               runIter j (EOF Nothing)
 
           (EOF e) -> return $ Cont undefined e
 
diff --git a/src/Snap/Internal/Http/Server.hs b/src/Snap/Internal/Http/Server.hs
index 2360a4f..40988ed 100644
--- a/src/Snap/Internal/Http/Server.hs
+++ b/src/Snap/Internal/Http/Server.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Snap.Internal.Http.Server where
@@ -299,9 +300,10 @@ runHTTP lh lip lp rip rp alog elog
 
     go = do
         buf <- mkIterateeBuffer
-        let iter = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $
-                                  httpSession writeEnd buf onSendFile tickle
-                                  handler
+        let iter1 = runServerMonad lh lip lp rip rp (logA alog) (logE elog) $
+                                   httpSession writeEnd buf onSendFile tickle
+                                   handler
+        let iter = iterateeDebugWrapper "httpSession iteratee" iter1
         readEnd iter >>= run
 
 
@@ -335,11 +337,15 @@ httpSession :: Iteratee IO ()                -- ^ write 
end of socket
             -> ServerMonad ()
 httpSession writeEnd' ibuf onSendFile tickle handler = do
 
-    writeEnd <- liftIO $ I.unsafeBufferIterateeWithBuffer ibuf writeEnd'
+    writeEnd1 <- liftIO $ I.unsafeBufferIterateeWithBuffer ibuf writeEnd'
+
+    let writeEnd = iterateeDebugWrapper "writeEnd" writeEnd1
 
     liftIO $ debug "Server.httpSession: entered"
     mreq  <- receiveRequest
 
+    
+
     -- successfully got a request, so restart timer
     liftIO tickle
 
@@ -354,6 +360,7 @@ httpSession writeEnd' ibuf onSendFile tickle handler = do
           checkExpect100Continue req writeEnd
 
           logerr <- gets _logError
+
           (req',rspOrig) <- lift $ handler logerr req
 
           liftIO $ debug $ "Server.httpSession: finished running user handler"
@@ -367,9 +374,11 @@ httpSession writeEnd' ibuf onSendFile tickle handler = do
                       else rspTmp
 
           liftIO $ debug "Server.httpSession: handled, skipping request body"
+
           srqEnum <- liftIO $ readIORef $ rqBody req'
           let (SomeEnumerator rqEnum) = srqEnum
-          lift $ joinIM $ rqEnum skipToEof
+          lift $ joinIM
+               $ rqEnum (iterateeDebugWrapper "httpSession/skipToEof" 
skipToEof)
           liftIO $ debug $ "Server.httpSession: request body skipped, " ++
                            "sending response"
 
@@ -464,13 +473,13 @@ receiveRequest = do
         hasContentLength :: Int -> ServerMonad ()
         hasContentLength l = do
             liftIO $ debug $ "receiveRequest/setEnumerator: " ++
-                             "request had content-length"
+                             "request had content-length " ++ Prelude.show l
             liftIO $ writeIORef (rqBody req) (SomeEnumerator e)
             liftIO $ debug "receiveRequest/setEnumerator: body enumerator set"
           where
             e :: Enumerator IO a
-            e = return . joinI . I.take l .
-                iterateeDebugWrapper "rqBody iterator"
+            e it = return $ joinI $ I.take l $
+                iterateeDebugWrapper "rqBody iterator" it
 
         noContentLength :: ServerMonad ()
         noContentLength = do
@@ -596,7 +605,7 @@ receiveRequest = do
 
 ------------------------------------------------------------------------------
 -- Response must be well-formed here
-sendResponse :: Response
+sendResponse :: forall a . Response
              -> Iteratee IO a
              -> (FilePath -> Int64 -> IO a)
              -> ServerMonad (Int64, a)
@@ -605,18 +614,18 @@ sendResponse rsp' writeEnd onSendFile = do
     let !headerString = mkHeaderString rsp
 
     (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)     -> liftIO $ whenEnum headerString e
-                  (SendFile f) -> liftIO $ whenSendFile headerString rsp f
+                  (Enum e)     -> lift $ whenEnum headerString e
+                  (SendFile f) -> lift $ whenSendFile headerString rsp f
 
     return $! (bs,x)
 
   where
     --------------------------------------------------------------------------
+    whenEnum :: ByteString -> (forall x . Enumerator IO x) -> Iteratee IO 
(a,Int64)
     whenEnum hs e = do
-        let enum = enumBS hs >. e
+        let enum = enumBS hs >. e >. enumEof
         let hl = fromIntegral $ S.length hs
-
-        (x,bs) <- liftIO $ enum (countBytes writeEnd) >>= run
+        (x,bs) <- joinIM $ enum (countBytes writeEnd)
 
         return (x, bs-hl)
 
@@ -624,10 +633,10 @@ sendResponse rsp' writeEnd onSendFile = do
     --------------------------------------------------------------------------
     whenSendFile hs r f = do
         -- guaranteed to have a content length here.
-        enumBS hs writeEnd >>= run
+        joinIM $ (enumBS hs >. enumEof) writeEnd
 
         let !cl = fromJust $ rspContentLength r
-        x <- onSendFile f cl
+        x <- liftIO $ onSendFile f cl
         return (x, cl)
 
 
@@ -657,8 +666,10 @@ sendResponse rsp' writeEnd onSendFile = do
             if sendChunked
               then do
                   let r' = setHeader "Transfer-Encoding" "chunked" r
-                  let e  = writeChunkedTransferEncoding $
-                           rspBodyToEnum $ rspBody r
+                  let origE = rspBodyToEnum $ rspBody r
+
+                  let e i = writeChunkedTransferEncoding i >>= origE
+
                   return $ r' { rspBody = Enum e }
 
               else do
@@ -682,7 +693,7 @@ sendResponse rsp' writeEnd onSendFile = do
             return $ r' { rspBody = b }
 
       where
-        i :: Enumerator IO a -> Enumerator IO a
+        i :: forall a . Enumerator IO a -> Enumerator IO a
         i enum iter = enum (joinI $ takeExactly cl iter)
 
 
diff --git a/test/suite/Snap/Internal/Http/Parser/Tests.hs 
b/test/suite/Snap/Internal/Http/Parser/Tests.hs
index e700a8c..f96a470 100644
--- a/test/suite/Snap/Internal/Http/Parser/Tests.hs
+++ b/test/suite/Snap/Internal/Http/Parser/Tests.hs
@@ -20,6 +20,7 @@ import           Data.Iteratee.WrappedByteString
 import           Data.List
 import qualified Data.Map as Map
 import           Data.Maybe (isNothing)
+import           Data.Monoid
 import           Test.Framework 
 import           Test.Framework.Providers.HUnit
 import           Test.Framework.Providers.QuickCheck2
@@ -32,6 +33,7 @@ import           Text.Printf
 import           Snap.Internal.Http.Parser
 import           Snap.Internal.Http.Types hiding (Enumerator)
 import           Snap.Iteratee hiding (foldl')
+import qualified Snap.Iteratee as I
 import           Snap.Test.Common()
 
 
@@ -41,7 +43,6 @@ tests = [ testShow
         , testChunked
         , testBothChunked
         , testBothChunkedBuffered1
-        , testBothChunkedBuffered2
         , testBothChunkedPipelined
         , testBothChunkedEmpty
         , testP2I
@@ -152,8 +153,10 @@ testBothChunked = testProperty "chunk . unchunk == id" $
                   monadicIO $ forAllM arbitrary prop
   where
     prop s = do
+        it <- QC.run $ writeChunkedTransferEncoding stream2stream
+
         bs <- QC.run $
-              writeChunkedTransferEncoding (enumBS s) stream2stream
+              enumBS s it
                 >>= run >>= return . unWrap
 
         let enum = enumBS bs
@@ -167,7 +170,7 @@ testBothChunked = testProperty "chunk . unchunk == id" $
 
 
 testBothChunkedBuffered1 :: Test
-testBothChunkedBuffered1 = testProperty "testBothChunkedBuffered1" $
+testBothChunkedBuffered1 = testProperty "testBothChunkedBuffered2" $
                            monadicIO prop
   where
     prop = do
@@ -176,52 +179,42 @@ testBothChunkedBuffered1 = testProperty 
"testBothChunkedBuffered1" $
         ntimes <- QC.pick (choose (4,7))
 
         let e = enumLBS s'
+        let n = fromEnum $ L.length s'
 
-        let enums = replicate ntimes (writeChunkedTransferEncoding e)
-
-        let mothra = foldl' (>.) (enumBS "") enums
-
-        ----------------------------------------------------------------------
-        -- first go, buffer, no cancellation
-        (inputIter1,_) <- QC.run $ bufferIteratee stream2stream
-        bs1 <- QC.run $ mothra inputIter1
-                 >>= run >>= return . unWrap
-        let e1 = enumBS bs1
-        let pcrlf = \s -> parserToIteratee $ string "\r\n" >> return s
-        iters <- QC.run $
-                 replicateM ntimes $
-                   readChunkedTransferEncoding stream2stream
-        let godzilla = sequence $ map (>>= pcrlf) iters
-        outiter1 <- QC.run $ e1 godzilla
-        x1 <- QC.run $ liftM (map unWrap) $ run outiter1
-
-        QC.assert $
-          (map (L.fromChunks . (:[])) x1) == (replicate ntimes s')
-
-
+        let enum = foldl' (>.) (enumBS "") (replicate ntimes e)
 
-testBothChunkedBuffered2 :: Test
-testBothChunkedBuffered2 = testProperty "testBothChunkedBuffered2" $
-                           monadicIO prop
-  where
-    prop = do
-        sz     <- QC.pick (choose (1000,4000))
-        s'     <- QC.pick $ resize sz arbitrary
-        ntimes <- QC.pick (choose (4,7))
+        (bufi,_) <- QC.run $ bufferIteratee stream2stream
+        iter' <- QC.run $ writeChunkedTransferEncoding bufi
+        let iter = I.joinI $ I.take n iter'
+        let iters = replicate ntimes iter
 
-        let e = enumLBS s'
+        let mothra = foldM (\s it -> it >>= \t -> return $ s `mappend` t)
+                           mempty
+                           iters
 
-        let enums = replicate ntimes (writeChunkedTransferEncoding e)
+        bs <- QC.run $ enum mothra
+                >>= run >>= return . unWrap
 
-        let mothra = foldl' (>.) (enumBS "") enums
 
         ----------------------------------------------------------------------
         -- 2nd pass, cancellation
         let pcrlf = \s -> parserToIteratee $ string "\r\n" >> return s
         (inputIter2,esc) <- QC.run $ bufferIteratee stream2stream
         QC.run $ writeIORef esc True
-        bs2 <- QC.run $ mothra inputIter2
+
+        iter2' <- QC.run $ writeChunkedTransferEncoding inputIter2
+        let iter2 = I.joinI $ I.take n iter2'
+        let iters2 = replicate ntimes iter2
+
+        let mothra2 = foldM (\s it -> it >>= \t -> return $ s `mappend` t)
+                            mempty
+                            iters2
+
+
+        bs2 <- QC.run $ enum mothra2
                  >>= run >>= return . unWrap
+
+
         let e2 = enumBS bs2
         iters' <- QC.run $
                   replicateM ntimes $
@@ -246,14 +239,21 @@ testBothChunkedPipelined = testProperty 
"testBothChunkedPipelined" $
         --let s' = L.take 2000 $ L.fromChunks $ repeat s
 
         let e = enumLBS s'
+        let n = fromEnum $ L.length s'
 
-        let enums = replicate ntimes (writeChunkedTransferEncoding e)
-
-        let mothra = foldl' (>.) (enumBS "") enums
+        let enum = foldl' (>.) (enumBS "") (replicate ntimes e)
 
         (bufi,_) <- QC.run $ bufferIteratee stream2stream
 
-        bs <- QC.run $ mothra bufi
+        iter' <- QC.run $ writeChunkedTransferEncoding bufi
+        let iter = I.joinI $ I.take n iter'
+
+        let iters = replicate ntimes iter
+        let mothra = foldM (\s it -> it >>= \t -> return $ s `mappend` t)
+                           mempty
+                           iters
+
+        bs <- QC.run $ enum mothra
                 >>= run >>= return . unWrap
 
         let e2 = enumBS bs
@@ -280,14 +280,20 @@ testBothChunkedEmpty = testCase "testBothChunkedEmpty" 
prop
     prop = do
         let s' = ""
         let e = enumLBS s'
+        let n = fromEnum $ L.length s'
 
         let ntimes = 5
+        let enum = foldl' (>.) (enumBS "") (replicate ntimes e)
 
-        let enums = replicate ntimes $ writeChunkedTransferEncoding e
+        iter' <- writeChunkedTransferEncoding stream2stream
+        let iter = I.joinI $ I.take n iter'
 
-        let mothra = foldl' (>.) (enumBS "") enums
+        let iters = replicate ntimes iter
+        let mothra = foldM (\s it -> it >>= \t -> return $ s `mappend` t)
+                           mempty
+                           iters
 
-        bs <- mothra stream2stream
+        bs <- enum mothra
                 >>= run >>= return . unWrap
 
         let e2 = enumBS bs
diff --git a/test/testserver/Main.hs b/test/testserver/Main.hs
index 354a78e..6a2d40c 100644
--- a/test/testserver/Main.hs
+++ b/test/testserver/Main.hs
@@ -10,6 +10,9 @@ import           Snap.Types
 import           Snap.Http.Server
 import           Snap.Util.FileServe
 
+
+import Snap.Internal.Iteratee.Debug
+
 {-
 
 /pong
@@ -35,7 +38,8 @@ echoHandler :: Snap ()
 echoHandler = do
     unsafeDetachRequestBody >>= \e -> do
       let (SomeEnumerator x) = e
-      modifyResponse $ setResponseBody x
+      let e' i = x (iterateeDebugWrapper "echoHandler" i)
+      modifyResponse $ setResponseBody e'
 
 
 responseHandler = do
@@ -69,6 +73,7 @@ main = do
 
   where
     go m = do
-        httpServe "*" 3000 "localhost" Nothing Nothing handlers 
+        httpServe "*" 3000 "localhost" (Just "ts-access.log")
+                  (Just "ts-error.log") handlers 
         putMVar m ()
 
-----------------------------------------------------------------------


hooks/post-receive
-- 
snap-server
_______________________________________________
Snap mailing list
[email protected]
http://mailman-mail5.webfaction.com/listinfo/snap

Reply via email to