on master help sign in
Compression working
42be430Michael Snoyman
Network/Wai/Middleware/Gzip.hs+6−9
@@ -20,6 +20,7 @@ import Network.Wai
20import Network.Wai.Zlib
20import Network.Wai.Zlib
21import Data.Maybe (fromMaybe)
21import Data.Maybe (fromMaybe)
22import qualified Data.ByteString.Char8 as B
22import qualified Data.ByteString.Char8 as B
23+import Data.Enumerator (($$), joinI)
23
24
24-- | Use gzip to compress the body of the response.
25-- | Use gzip to compress the body of the response.
25--
26--
@@ -39,8 +40,7 @@ gzip files app env = do
39 Nothing -> return res
40 Nothing -> return res
40 Just enum -> return $ ResponseEnumerator $ compressE enum
41 Just enum -> return $ ResponseEnumerator $ compressE enum
41 where
42 where
42− shouldGzip (ResponseFile _ hs _)
43+ shouldGzip ResponseFile{} | not files = Nothing
43− | not files = Nothing
44 shouldGzip res =
44 shouldGzip res =
45 if "gzip" `elem` enc
45 if "gzip" `elem` enc
46 then Just $ responseEnumerator res
46 then Just $ responseEnumerator res
@@ -53,13 +53,10 @@ compressE re f =
53 re f'
53 re f'
54 --e s hs'
54 --e s hs'
55 where
55 where
56− f' = undefined
56+ f' s hs =
57+ joinI $ compress $$ f s hs'
58+ where
57− --hs' = ("Content-Encoding", "gzip") : hs
59+ hs' = ("Content-Encoding", "gzip") : hs
58−
59−{-
60−compressE :: ResponseBody -> ResponseBody
61−compressE = ResponseEnumerator . compress . fromResponseBody
62−-}
63
60
64splitCommas :: String -> [String]
61splitCommas :: String -> [String]
65splitCommas [] = []
62splitCommas [] = []
Network/Wai/Zlib.hs+35−23
@@ -1,36 +1,48 @@
1module Network.Wai.Zlib (compress) where
1module Network.Wai.Zlib (compress) where
2
2
3−import Prelude
3+import Prelude hiding (head)
4import Network.Wai
4import Network.Wai
5import Data.ByteString (ByteString)
5import Data.ByteString (ByteString)
6−import Data.Enumerator (Enumeratee)
6+import Data.Enumerator
7+ ( Enumeratee, checkDone, Stream (..), continue
8+ , (>>==), head, ($$), joinI
9+ )
7−import Blaze.ByteString.Builder (Builder)
10+import Blaze.ByteString.Builder (Builder, fromByteString)
11+import Blaze.ByteString.Builder.Enumerator (builderToByteString)
12+import Control.Monad.IO.Class (liftIO)
8
13
9import Codec.Zlib
14import Codec.Zlib
10
15
16+-- Note: this function really should return a stream of ByteStrings, but the
17+-- WAI protocol needs Builders anyway.
11compress :: Enumeratee Builder Builder IO a
18compress :: Enumeratee Builder Builder IO a
12−compress = undefined
19+compress step0 = joinI $ builderToByteString $$ do
13− {-
14− Enumerator $ \iter acc -> do
15− def <- initDeflate 7 $ WindowBits 31
20+ def <- liftIO $ initDeflate 7 $ WindowBits 31
16− compressInner iter acc enum def
21+ loop def step0
22+ where
23+ loop def = checkDone $ step def
24+ step def k = do
25+ minput <- head
26+ case minput of
27+ Nothing -> do
28+ bss <- liftIO $ finishDeflate def drain
29+ k (Chunks bss) >>== return
30+ Just input -> do
31+ bss <- liftIO $ withDeflateInput def input drain
32+ case bss of
33+ [] -> step def k
34+ _ -> k (Chunks bss) >>== loop def
17
35
18−compressInner :: (acc -> ByteString -> IO (Either acc acc))
36+drain =
19− -> acc
37+ go id
20− -> Enumerator
38+ where
21− -> Deflate
39+ go front mbs' = do
22− -> IO (Either acc acc)
40+ mbs <- mbs'
23−compressInner iter acc enum def = do
24− eacc <- runEnumerator enum (compressIter iter def) acc
25− case eacc of
41+ case mbs of
26− Left acc' -> return $ Left acc'
42+ Nothing -> return $ map fromByteString $ front []
27− Right acc' -> finishStream iter def acc'
43+ Just bs -> go (front . (:) bs) mbs'
28
44
29−finishStream :: (acc -> ByteString -> IO (Either acc acc))
45+ {-
30− -> Deflate
31− -> acc
32− -> IO (Either acc acc)
33−finishStream iter def acc = finishDeflate def $ drain iter acc
34
46
35compressIter :: (acc -> ByteString -> IO (Either acc acc))
47compressIter :: (acc -> ByteString -> IO (Either acc acc))
36 -> Deflate
48 -> Deflate
proxy.hs+2−1
@@ -1,6 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2import qualified Network.HTTP.Enumerator as H
2import qualified Network.HTTP.Enumerator as H
3import qualified Network.Wai as W
3import qualified Network.Wai as W
4+import Network.Wai.Middleware.Gzip (gzip)
4import Network.Wai.Handler.SimpleServer (run)
5import Network.Wai.Handler.SimpleServer (run)
5import qualified Data.ByteString.Char8 as S8
6import qualified Data.ByteString.Char8 as S8
6import qualified Data.ByteString.Lazy.Char8 ()
7import qualified Data.ByteString.Lazy.Char8 ()
@@ -9,7 +10,7 @@ import Blaze.ByteString.Builder (fromByteString)
9import qualified Data.Enumerator as E
10import qualified Data.Enumerator as E
10
11
11main :: IO ()
12main :: IO ()
12−main = run 3000 app
13+main = run 3000 $ gzip False app
13
14
14app :: W.Application a
15app :: W.Application a
15app W.Request { W.pathInfo = path } =
16app W.Request { W.pathInfo = path } =