diff --git a/hack2-contrib.cabal b/hack2-contrib.cabal
--- a/hack2-contrib.cabal
+++ b/hack2-contrib.cabal
@@ -1,5 +1,5 @@
 Name:                 hack2-contrib
-Version:              2011.6.13
+Version:              2011.6.19
 Build-type:           Simple
 Synopsis:             Hack2 contrib
 Description:          Common middlewares and utilities that helps working with Hack2
@@ -28,11 +28,12 @@
                   , bytestring
                   , data-default >= 0.2
                   , time
-                  , air >= 2011.6.11
-                  , hack2 >= 2009.10.30
+                  , air >= 2011.6.19
+                  , hack2 >= 2011.6.19
                   , utf8-string
                   -- , ansi-wl-pprint
                   , regexpr
+                  , enumerator < 5
                   
   hs-source-dirs: src/
   
diff --git a/src/Hack2/Contrib/AirBackports.hs b/src/Hack2/Contrib/AirBackports.hs
--- a/src/Hack2/Contrib/AirBackports.hs
+++ b/src/Hack2/Contrib/AirBackports.hs
@@ -11,7 +11,7 @@
 import Text.RegexPR
 import Data.Maybe
 
-import Air.Env
+import Air.Env hiding (Default, def)
 import Prelude ()
 
 b2u, u2b :: String -> String
diff --git a/src/Hack2/Contrib/Middleware/Cascade.hs b/src/Hack2/Contrib/Middleware/Cascade.hs
--- a/src/Hack2/Contrib/Middleware/Cascade.hs
+++ b/src/Hack2/Contrib/Middleware/Cascade.hs
@@ -1,7 +1,7 @@
 module Hack2.Contrib.Middleware.Cascade (cascade) where
 
 import Prelude ()
-import Air.Env
+import Air.Env hiding (Default, def)
 import Hack2
 import Data.Default
 
diff --git a/src/Hack2/Contrib/Middleware/ContentLength.hs b/src/Hack2/Contrib/Middleware/ContentLength.hs
--- a/src/Hack2/Contrib/Middleware/ContentLength.hs
+++ b/src/Hack2/Contrib/Middleware/ContentLength.hs
@@ -16,9 +16,11 @@
   response <- app env
   
   if should_size response
-    then response
-      .set_header _ContentLength (response.body.bytesize.show_bytestring) .return
-    else response .return
+    then do
+      size <- response.body_bytestring ^ bytesize ^ show_bytestring
+      return - response.set_header _ContentLength size
+    else 
+      return - response
   
   where 
     should_size response =
diff --git a/src/Hack2/Contrib/Middleware/File.hs b/src/Hack2/Contrib/Middleware/File.hs
--- a/src/Hack2/Contrib/Middleware/File.hs
+++ b/src/Hack2/Contrib/Middleware/File.hs
@@ -15,7 +15,7 @@
 import Hack2.Contrib.Response
 import Hack2.Contrib.Utils
 import Hack2.Contrib.AirBackports
-import Air.Env
+import Air.Env hiding (Default, def)
 import Prelude ()
 import System.Directory
 import System.FilePath
@@ -60,7 +60,7 @@
         
         return - 
           def 
-            .set_body content
+            .set_body_bytestring content
             .set_content_length size
             .set_content_type content_type
             .set_last_modified (B.pack mtime_str)
@@ -72,7 +72,7 @@
     .set_status 404
     .set_content_type _TextPlain
     .set_content_length (msg.B.length)
-    .set_body msg
+    .set_body_bytestring msg
 
   where msg = "No permission: " + path + "\n"
 
@@ -82,7 +82,7 @@
     .set_status 404
     .set_content_type _TextPlain
     .set_content_length (msg.B.length)
-    .set_body msg
+    .set_body_bytestring msg
   
   where msg = "File not found: " + path + "\n"
 
@@ -92,7 +92,7 @@
     .set_status 403
     .set_content_type _TextPlain
     .set_content_length (msg.B.length)
-    .set_body msg
+    .set_body_bytestring msg
 
   where msg = "Forbidden\n"
   
diff --git a/src/Hack2/Contrib/Middleware/Head.hs b/src/Hack2/Contrib/Middleware/Head.hs
--- a/src/Hack2/Contrib/Middleware/Head.hs
+++ b/src/Hack2/Contrib/Middleware/Head.hs
@@ -3,14 +3,15 @@
 import Hack2
 import Hack2.Contrib.Response
 import Hack2.Contrib.Utils
-import Air.Light
-import Prelude hiding ((.), (^), (>), head)
-import qualified Data.ByteString.Lazy.Char8 as B
 
+import Air.Env hiding (def, head)
+import Prelude ()
+import qualified Data.ByteString.Lazy.Char8 as B
+import Data.Default (def)
 
 head :: Middleware
 head app = \env -> do
   response <- app env
   if env.request_method.is HEAD 
-    then response .set_body B.empty .set_content_length 0 .return
+    then response .set_body def .set_content_length 0 .return
     else response .return
diff --git a/src/Hack2/Contrib/Middleware/SimpleAccessLogger.hs b/src/Hack2/Contrib/Middleware/SimpleAccessLogger.hs
--- a/src/Hack2/Contrib/Middleware/SimpleAccessLogger.hs
+++ b/src/Hack2/Contrib/Middleware/SimpleAccessLogger.hs
@@ -9,7 +9,7 @@
 import Hack2.Contrib.Constants
 import Hack2.Contrib.Utils
 import Hack2.Contrib.AirBackports
-import Air.Env
+import Air.Env hiding (Default, def)
 import Data.Maybe
 import Prelude ()
 import qualified Data.ByteString.Lazy.Char8 as B
diff --git a/src/Hack2/Contrib/Middleware/URLMap.hs b/src/Hack2/Contrib/Middleware/URLMap.hs
--- a/src/Hack2/Contrib/Middleware/URLMap.hs
+++ b/src/Hack2/Contrib/Middleware/URLMap.hs
@@ -15,7 +15,7 @@
 import Hack2
 import Hack2.Contrib.Utils
 import List (find, isPrefixOf)
-import Air.Env
+import Air.Env hiding (Default, def)
 import Prelude ()
 import qualified Data.ByteString.Lazy.Char8 as B
 
diff --git a/src/Hack2/Contrib/Middleware/XForwardedForToRemoteHost.hs b/src/Hack2/Contrib/Middleware/XForwardedForToRemoteHost.hs
--- a/src/Hack2/Contrib/Middleware/XForwardedForToRemoteHost.hs
+++ b/src/Hack2/Contrib/Middleware/XForwardedForToRemoteHost.hs
@@ -3,7 +3,7 @@
 module Hack2.Contrib.Middleware.XForwardedForToRemoteHost (x_forwarded_for_to_remote_host) where
 
 import Hack2
-import Air.Env
+import Air.Env hiding (Default, def)
 import Prelude ()
 import Data.ByteString.Lazy.Char8 ()
 
diff --git a/src/Hack2/Contrib/Request.hs b/src/Hack2/Contrib/Request.hs
--- a/src/Hack2/Contrib/Request.hs
+++ b/src/Hack2/Contrib/Request.hs
@@ -8,7 +8,7 @@
 import Hack2 hiding (body)
 import Hack2.Contrib.Constants
 import Hack2.Contrib.Utils
-import Air.Env
+import Air.Env hiding (Default, def)
 import Network.CGI.Cookie
 import Network.CGI.Protocol
 import Prelude ()
@@ -16,8 +16,8 @@
 import Hack2.Contrib.AirBackports
 
 
-body :: Env -> ByteString
-body = hack_input
+input_bytestring :: Env -> IO ByteString
+input_bytestring = hack_input > unHackEnumerator > fromEnumerator
 
 scheme :: Env -> ByteString
 scheme = hack_url_scheme > show > lower > B.pack
@@ -65,16 +65,19 @@
     then []
     else env.query_string.B.unpack.formDecode.map_both B.pack
 
-inputs :: Env -> [(ByteString, ByteString)]
-inputs env = 
-  env
-    .httpHeaders
-    .map_fst (B.unpack > upper > gsub "-" "_") -- cgi env use all cap letters
-    .map_snd B.unpack
-    .(("REQUEST_METHOD", env.request_method.show) : ) -- for cgi request
-    .flip decodeInput (env.body)
-    .fst
-    .concatMap to_headers
+inputs :: Env -> IO [(ByteString, ByteString)]
+inputs env = do
+  _body <- env.input_bytestring
+  return - 
+    env
+      .httpHeaders
+      .map_fst (B.unpack > upper > gsub "-" "_") -- cgi env use all cap letters
+      .map_snd B.unpack
+      .(("REQUEST_METHOD", env.request_method.show) : ) -- for cgi request
+      .flip decodeInput _body
+      .fst
+      .concatMap to_headers
+      
   where
     to_headers (k, input) = case input.inputFilename of
       Nothing -> [(k.B.pack, input.inputValue)]
diff --git a/src/Hack2/Contrib/Response.hs b/src/Hack2/Contrib/Response.hs
--- a/src/Hack2/Contrib/Response.hs
+++ b/src/Hack2/Contrib/Response.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ExistentialQuantification #-}
 
 module Hack2.Contrib.Response where
 
@@ -7,11 +8,16 @@
 import Hack2
 import Hack2.Contrib.Constants
 import Hack2.Contrib.Utils
-import Air.Env
-import Prelude hiding ((.), (^), (>), (+))
+import Air.Env hiding (def)
+import Prelude ()
 import qualified Data.ByteString.Lazy.Char8 as B
 import Hack2.Contrib.AirBackports
+import Data.Default (def)
+import Data.Enumerator (run_, enumList, Enumerator, ($$))
+import qualified Data.ByteString.Char8 as Strict
 
+body_bytestring :: Response -> IO B.ByteString
+body_bytestring r = r.body.unHackEnumerator.fromEnumerator
 
 redirect :: ByteString -> Maybe Int -> Response -> Response
 redirect target code = 
@@ -22,7 +28,7 @@
 finish r 
   | r.status.belongs_to [204, 304]
       = r .delete_header _ContentType
-          .set_body B.empty
+          .set_body def
   | otherwise = r
 
 
@@ -44,8 +50,14 @@
 set_content_length :: (Integral a) => a -> Response -> Response
 set_content_length i r = r.set_header _ContentLength (i.show_bytestring)
 
-set_body :: ByteString -> Response -> Response
+set_body :: HackEnumerator -> Response -> Response
 set_body s r = r { body = s }
+
+set_body_bytestring :: B.ByteString -> Response -> Response
+set_body_bytestring b r = 
+  let enum = b.toEnumerator :: (forall a. Enumerator Strict.ByteString IO a)
+  in
+  set_body (HackEnumerator enum) r
 
 set_status :: Int -> Response -> Response
 set_status i r = r { status = i }
diff --git a/src/Hack2/Contrib/Utils.hs b/src/Hack2/Contrib/Utils.hs
--- a/src/Hack2/Contrib/Utils.hs
+++ b/src/Hack2/Contrib/Utils.hs
@@ -10,14 +10,33 @@
 import Data.Time
 import Hack2
 import Hack2.Contrib.Constants
-import Air.Light
+import Air.Env hiding (def)
+import Data.Default (def)
 import Network.URI hiding (path)
-import Prelude hiding ((.), (^), (>), lookup, (+), (/), (-))
+import Prelude ()
 import System.Locale (defaultTimeLocale)
 import qualified Data.ByteString.Lazy.Char8 as B
 import qualified Data.Map as M
 import Hack2.Contrib.AirBackports
 
+import qualified Data.ByteString.Char8 as Strict
+
+import qualified Data.Enumerator.Binary as EB
+import qualified Data.Enumerator.List as EL
+
+import Data.Enumerator (run_, enumList, Enumerator, ($$))
+
+fromEnumerator :: Monad m => Enumerator Strict.ByteString m B.ByteString -> m B.ByteString
+fromEnumerator m = run_ - m $$ EB.consume
+
+toEnumerator :: Monad m => B.ByteString -> Enumerator Strict.ByteString m a
+toEnumerator = enumList 1 < B.toChunks
+
+withEnumerator :: Monad m => (B.ByteString -> B.ByteString) -> Enumerator Strict.ByteString m B.ByteString -> m (Enumerator Strict.ByteString m a)
+withEnumerator f enum = do
+  bytes <- fromEnumerator enum
+  return - toEnumerator - f bytes
+
 empty_app :: Application
 empty_app = return def
 
@@ -82,7 +101,7 @@
 server_port       :: Env -> Int
 hack_version      :: Env -> (Int, Int, Int)
 hack_url_scheme   :: Env -> HackUrlScheme
-hack_input        :: Env -> ByteString
+hack_input        :: Env -> HackEnumerator
 hack_errors       :: Env -> HackErrors
 hack_headers       :: Env -> [(ByteString, ByteString)]
 
