on master help sign in
Compression working
commit42be430c47cc9eeef690a1ef7a45417f83baae36 authorMichael Snoyman <michael@snoyman.com> dateWed 15 Dec 2010, 19:51 (16 years ago) parent5672e6b
3 files changed+43−33
Network/Wai/Middleware/Gzip.hs+6−9 Network/Wai/Zlib.hs+35−23 proxy.hs+2−1
Network/Wai/Middleware/Gzip.hs+6−9
@@ -20,6 +20,7 @@ import Network.Wai
2020import Network.Wai.Zlib
2121import Data.Maybe (fromMaybe)
2222import qualified Data.ByteString.Char8 as B
23+import Data.Enumerator (($$), joinI)
2324
2425-- | Use gzip to compress the body of the response.
2526--
@@ -39,8 +40,7 @@ gzip files app env = do
3940 Nothing -> return res
4041 Just enum -> return $ ResponseEnumerator $ compressE enum
4142 where
42− shouldGzip (ResponseFile _ hs _)
43− | not files = Nothing
43+ shouldGzip ResponseFile{} | not files = Nothing
4444 shouldGzip res =
4545 if "gzip" `elem` enc
4646 then Just $ responseEnumerator res
@@ -53,13 +53,10 @@ compressE re f =
5353 re f'
5454 --e s hs'
5555 where
56− f' = undefined
57− --hs' = ("Content-Encoding", "gzip") : hs
58−
59−{-
60−compressE :: ResponseBody -> ResponseBody
61−compressE = ResponseEnumerator . compress . fromResponseBody
62−-}
56+ f' s hs =
57+ joinI $ compress $$ f s hs'
58+ where
59+ hs' = ("Content-Encoding", "gzip") : hs
6360
6461splitCommas :: String -> [String]
6562splitCommas [] = []
Network/Wai/Zlib.hs+35−23
@@ -1,36 +1,48 @@
11module Network.Wai.Zlib (compress) where
22
3−import Prelude
3+import Prelude hiding (head)
44import Network.Wai
55import Data.ByteString (ByteString)
6−import Data.Enumerator (Enumeratee)
7−import Blaze.ByteString.Builder (Builder)
6+import Data.Enumerator
7+ ( Enumeratee, checkDone, Stream (..), continue
8+ , (>>==), head, ($$), joinI
9+ )
10+import Blaze.ByteString.Builder (Builder, fromByteString)
11+import Blaze.ByteString.Builder.Enumerator (builderToByteString)
12+import Control.Monad.IO.Class (liftIO)
813
914import Codec.Zlib
1015
16+-- Note: this function really should return a stream of ByteStrings, but the
17+-- WAI protocol needs Builders anyway.
1118compress :: Enumeratee Builder Builder IO a
12−compress = undefined
13− {-
14− Enumerator $ \iter acc -> do
15− def <- initDeflate 7 $ WindowBits 31
16− compressInner iter acc enum def
19+compress step0 = joinI $ builderToByteString $$ do
20+ def <- liftIO $ initDeflate 7 $ WindowBits 31
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
1735
18−compressInner :: (acc -> ByteString -> IO (Either acc acc))
19− -> acc
20− -> Enumerator
21− -> Deflate
22− -> IO (Either acc acc)
23−compressInner iter acc enum def = do
24− eacc <- runEnumerator enum (compressIter iter def) acc
25− case eacc of
26− Left acc' -> return $ Left acc'
27− Right acc' -> finishStream iter def acc'
36+drain =
37+ go id
38+ where
39+ go front mbs' = do
40+ mbs <- mbs'
41+ case mbs of
42+ Nothing -> return $ map fromByteString $ front []
43+ Just bs -> go (front . (:) bs) mbs'
2844
29−finishStream :: (acc -> ByteString -> IO (Either acc acc))
30− -> Deflate
31− -> acc
32− -> IO (Either acc acc)
33−finishStream iter def acc = finishDeflate def $ drain iter acc
45+ {-
3446
3547compressIter :: (acc -> ByteString -> IO (Either acc acc))
3648 -> Deflate
proxy.hs+2−1
@@ -1,6 +1,7 @@
11{-# LANGUAGE OverloadedStrings #-}
22import qualified Network.HTTP.Enumerator as H
33import qualified Network.Wai as W
4+import Network.Wai.Middleware.Gzip (gzip)
45import Network.Wai.Handler.SimpleServer (run)
56import qualified Data.ByteString.Char8 as S8
67import qualified Data.ByteString.Lazy.Char8 ()
@@ -9,7 +10,7 @@ import Blaze.ByteString.Builder (fromByteString)
910import qualified Data.Enumerator as E
1011
1112main :: IO ()
12−main = run 3000 app
13+main = run 3000 $ gzip False app
1314
1415app :: W.Application a
1516app W.Request { W.pathInfo = path } =