diff --git a/snap-server.cabal b/snap-server.cabal
--- a/snap-server.cabal
+++ b/snap-server.cabal
@@ -1,5 +1,5 @@
 name:           snap-server
-version:        0.2.12
+version:        0.2.13
 synopsis:       A fast, iteratee-based, epoll-enabled web server for the Snap Framework
 description:
   This is the first developer prerelease of the Snap framework.  Snap is a
@@ -122,7 +122,7 @@
     murmur-hash >= 0.1 && < 0.2,
     network == 2.2.1.*,
     old-locale,
-    snap-core >= 0.2.12 && <0.3,
+    snap-core >= 0.2.13 && <0.3,
     template-haskell,
     time,
     transformers,
diff --git a/src/Snap/Internal/Http/Server.hs b/src/Snap/Internal/Http/Server.hs
--- a/src/Snap/Internal/Http/Server.hs
+++ b/src/Snap/Internal/Http/Server.hs
@@ -280,7 +280,8 @@
         -> Maybe Logger                  -- ^ error logger
         -> Enumerator IO ()              -- ^ read end of socket
         -> Iteratee IO ()                -- ^ write end of socket
-        -> (FilePath -> Int64 -> IO ())  -- ^ sendfile end
+        -> (FilePath -> Int64 -> Int64 -> IO ())
+                                         -- ^ sendfile end
         -> IO ()                         -- ^ timeout tickler
         -> ServerHandler                 -- ^ handler procedure
         -> IO ()
@@ -330,7 +331,8 @@
 -- | Runs an HTTP session.
 httpSession :: Iteratee IO ()                -- ^ write end of socket
             -> ForeignPtr CChar              -- ^ iteratee buffer
-            -> (FilePath -> Int64 -> IO ())  -- ^ sendfile continuation
+            -> (FilePath -> Int64 -> Int64 -> IO ())
+                                             -- ^ sendfile continuation
             -> IO ()                         -- ^ timeout tickler
             -> ServerHandler                 -- ^ handler procedure
             -> ServerMonad ()
@@ -384,7 +386,7 @@
           date <- liftIO getDateString
           let ins = Map.insert "Date" [date] . Map.insert "Server" sERVER_HEADER
           let rsp' = updateHeaders ins rsp
-          (bytesSent,_) <- sendResponse rsp' writeEnd onSendFile
+          (bytesSent,_) <- sendResponse req rsp' writeEnd onSendFile
 
           liftIO . debug $ "Server.httpSession: sent " ++
                            (Prelude.show bytesSent) ++ " bytes"
@@ -604,17 +606,21 @@
 
 ------------------------------------------------------------------------------
 -- Response must be well-formed here
-sendResponse :: forall a . Response
+sendResponse :: forall a . Request
+             -> Response
              -> Iteratee IO a
-             -> (FilePath -> Int64 -> IO a)
+             -> (FilePath -> Int64 -> Int64 -> IO a)
              -> ServerMonad (Int64, a)
-sendResponse rsp' writeEnd onSendFile = do
+sendResponse req rsp' writeEnd onSendFile = do
     rsp <- fixupResponse rsp'
     let !headerString = mkHeaderString rsp
 
     (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)     -> lift $ whenEnum headerString rsp e
-                  (SendFile f) -> lift $ whenSendFile headerString rsp f
+                  (Enum e)             -> lift $ whenEnum headerString rsp e
+                  (SendFile f Nothing) -> lift $
+                                          whenSendFile headerString rsp f 0
+                  (SendFile f (Just (st,_))) ->
+                      lift $ whenSendFile headerString rsp f st
 
     return $! (bs,x)
 
@@ -636,12 +642,12 @@
 
 
     --------------------------------------------------------------------------
-    whenSendFile hs r f = do
+    whenSendFile hs r f start = do
         -- guaranteed to have a content length here.
         joinIM $ (enumBS hs >. enumEof) writeEnd
 
         let !cl = fromJust $ rspContentLength r
-        x <- liftIO $ onSendFile f cl
+        x <- liftIO $ onSendFile f start cl
         return (x, cl)
 
 
@@ -692,8 +698,8 @@
             -- set the content-length header
             let r' = setHeader "Content-Length" (l2s $ show cl) r
             let b = case (rspBody r') of
-                      (Enum e)     -> Enum (i e)
-                      (SendFile f) -> SendFile f
+                      (Enum e)       -> Enum (i e)
+                      (SendFile f m) -> SendFile f m
 
             return $ r' { rspBody = b }
 
@@ -720,23 +726,31 @@
 
     --------------------------------------------------------------------------
     fixupResponse :: Response -> ServerMonad Response
-    fixupResponse r =
-        {-# SCC "fixupResponse" #-}
-        do
-            let r' = updateHeaders (Map.delete "Content-Length") r
+    fixupResponse r = {-# SCC "fixupResponse" #-} do
+        let r' = deleteHeader "Content-Length" r
 
-            let code = rspStatus r'
+        let code = rspStatus r'
 
-            let r'' = if code == 204 || code == 304
-                       then handle304 r'
-                       else r'
+        let r'' = if code == 204 || code == 304
+                   then handle304 r'
+                   else r'
 
-            r''' <- case (rspBody r'') of
-                     (Enum _)     -> return r''
-                     (SendFile f) -> setFileSize f r''
-            case (rspContentLength r''') of
-              Nothing   -> noCL r'''
-              (Just sz) -> hasCL sz r'''
+        r''' <- do
+            z <- case (rspBody r'') of
+                   (Enum _)                  -> return r''
+                   (SendFile f Nothing)      -> setFileSize f r''
+                   (SendFile _ (Just (s,e))) -> return $
+                                                setContentLength (e-s) r''
+
+            case (rspContentLength z) of
+              Nothing   -> noCL z
+              (Just sz) -> hasCL sz z
+
+        -- HEAD requests cannot have bodies per RFC 2616 sec. 9.4
+        if rqMethod req == HEAD
+          then return $ deleteHeader "Transfer-Encoding"
+                      $ r''' { rspBody = Enum $ enumBS "" }
+          else return r'''
 
 
     --------------------------------------------------------------------------
diff --git a/src/Snap/Internal/Http/Server/LibevBackend.hs b/src/Snap/Internal/Http/Server/LibevBackend.hs
--- a/src/Snap/Internal/Http/Server/LibevBackend.hs
+++ b/src/Snap/Internal/Http/Server/LibevBackend.hs
@@ -112,12 +112,8 @@
 name = "libev"
 
 
-sendFile :: Connection -> FilePath -> Int64 -> IO ()
-#if defined(HAS_SENDFILE)
-sendFile c fp sz = do
-#else
-sendFile c fp _ = do
-#endif
+sendFile :: Connection -> FilePath -> Int64 -> Int64 -> IO ()
+sendFile c fp start sz = do
     withMVar lock $ \_ -> do
       act <- readIORef $ _writeActive c
       when act $ evIoStop loop io
@@ -127,10 +123,9 @@
 #if defined(HAS_SENDFILE)
     bracket (openFd fp ReadOnly Nothing defaultFileFlags)
             (closeFd)
-            (go 0 sz)
+            (go start sz)
 #else
-    -- no need to count bytes
-    enumFile fp (getWriteEnd c) >>= run
+    enumFilePartial fp (start,start+sz) (getWriteEnd c) >>= run
     return ()
 #endif
 
diff --git a/src/Snap/Internal/Http/Server/SimpleBackend.hs b/src/Snap/Internal/Http/Server/SimpleBackend.hs
--- a/src/Snap/Internal/Http/Server/SimpleBackend.hs
+++ b/src/Snap/Internal/Http/Server/SimpleBackend.hs
@@ -97,12 +97,12 @@
 name = "simple"
 
 
-sendFile :: Connection -> FilePath -> Int64 -> IO ()
+sendFile :: Connection -> FilePath -> Int64 -> Int64 -> IO ()
 #if defined(HAS_SENDFILE)
-sendFile c fp sz = do
+sendFile c fp start sz = do
     bracket (openFd fp ReadOnly Nothing defaultFileFlags)
             (closeFd)
-            (go 0 sz)
+            (go start sz)
   where
     go off bytes fd
       | bytes == 0 = return ()
@@ -114,9 +114,9 @@
 
     sfd = Fd . fdSocket $ _socket c
 #else
-sendFile c fp _ = do
+sendFile c fp start sz = do
     -- no need to count bytes
-    enumFile fp (getWriteEnd c) >>= run
+    enumFilePartial fp (start,start+sz) (getWriteEnd c) >>= run
     return ()
 #endif
 
diff --git a/test/runTestsAndCoverage.sh b/test/runTestsAndCoverage.sh
--- a/test/runTestsAndCoverage.sh
+++ b/test/runTestsAndCoverage.sh
@@ -2,7 +2,7 @@
 
 set -e
 
-if [ "x$DEBUG" == "x" ]; then
+if [ -z "$DEBUG" ]; then
     export DEBUG=testsuite
 fi
 
diff --git a/test/suite/Snap/Internal/Http/Server/Tests.hs b/test/suite/Snap/Internal/Http/Server/Tests.hs
--- a/test/suite/Snap/Internal/Http/Server/Tests.hs
+++ b/test/suite/Snap/Internal/Http/Server/Tests.hs
@@ -7,14 +7,14 @@
   ( tests ) where
 
 import             Control.Concurrent
-import             Control.Exception (try, throwIO, SomeException)
+import             Control.Exception (try, throwIO, bracket, SomeException)
 import             Control.Monad
 import "monads-fd" Control.Monad.Trans
 import qualified   Data.ByteString.Char8 as S
 import qualified   Data.ByteString.Lazy as L
 import qualified   Data.ByteString.Lazy.Char8 as LC
 import             Data.ByteString (ByteString)
-import             Data.ByteString.Internal (c2w, w2c)
+import             Data.ByteString.Internal (c2w)
 import             Data.Char
 import             Data.Int
 import             Data.IORef
@@ -29,6 +29,7 @@
 import qualified   Network.Socket.ByteString as N
 import             Prelude hiding (take)
 import qualified   Prelude
+import             System.Timeout
 import             Test.Framework
 import             Test.Framework.Providers.HUnit
 import             Test.HUnit hiding (Test, path)
@@ -148,6 +149,12 @@
   step acc str        = return $ Done acc str
 
 
+mkRequest :: ByteString -> IO Request
+mkRequest s = do
+    iter <- enumBS s $ liftM fromJust $ rsm receiveRequest
+    run iter
+
+
 testHttpRequest1 :: Test
 testHttpRequest1 =
     testCase "server/HttpRequest1" $ do
@@ -239,7 +246,7 @@
 expectException m = do
     e <- try m
     case e of
-      Left (z::SomeException)  -> return ()
+      Left (_::SomeException)  -> return ()
       Right _ -> assertFailure "expected exception, didn't get it"
 
 
@@ -381,10 +388,14 @@
 
 testHttpResponse1 :: Test
 testHttpResponse1 = testCase "server/HttpResponse1" $ do
-    let onSendFile = \f _ -> enumFile f copyingStream2stream >>= run
+    let onSendFile = \f start sz ->
+                     enumFilePartial f (start,start+sz) copyingStream2stream
+                                         >>= run
 
+    req <- mkRequest sampleRequest
+
     b <- run $ rsm $
-         sendResponse rsp1 copyingStream2stream onSendFile >>=
+         sendResponse req rsp1 copyingStream2stream onSendFile >>=
                       return . fromWrap . snd
 
     assertEqual "http response" (L.concat [
@@ -405,10 +416,13 @@
 
 testHttpResponse2 :: Test
 testHttpResponse2 = testCase "server/HttpResponse2" $ do
-    let onSendFile = \f _ -> enumFile f copyingStream2stream >>= run
+    let onSendFile = \f st sz ->
+                     enumFilePartial f (st,st+sz) copyingStream2stream >>= run
 
+    req <- mkRequest sampleRequest
+
     b2 <- run $ rsm $
-          sendResponse rsp2 copyingStream2stream onSendFile >>=
+          sendResponse req rsp2 copyingStream2stream onSendFile >>=
                        return . fromWrap . snd
 
     assertEqual "http response" (L.concat [
@@ -429,10 +443,13 @@
 
 testHttpResponse3 :: Test
 testHttpResponse3 = testCase "server/HttpResponse3" $ do
-    let onSendFile = \f _ -> enumFile f copyingStream2stream >>= run
+    let onSendFile = \f st sz ->
+                     enumFilePartial f (st,st+sz) copyingStream2stream >>= run
 
+    req <- mkRequest sampleRequest
+
     b3 <- run $ rsm $
-          sendResponse rsp3 copyingStream2stream onSendFile >>=
+          sendResponse req rsp3 copyingStream2stream onSendFile >>=
                        return . fromWrap . snd
 
     assertEqual "http response" b3 $ L.concat [
@@ -459,10 +476,13 @@
 
 testHttpResponse4 :: Test
 testHttpResponse4 = testCase "server/HttpResponse4" $ do
-    let onSendFile = \f _ -> enumFile f copyingStream2stream >>= run
+    let onSendFile = \f st sz ->
+                     enumFilePartial f (st,st+sz) copyingStream2stream >>= run
 
+    req <- mkRequest sampleRequest
+
     b <- run $ rsm $
-         sendResponse rsp1 copyingStream2stream onSendFile >>=
+         sendResponse req rsp1 copyingStream2stream onSendFile >>=
                       return . fromWrap . snd
 
     assertEqual "http response" (L.concat [
@@ -540,14 +560,15 @@
     assertBool "pipelined responses" ok
 
 
-mkIter :: IORef L.ByteString -> (Iteratee IO (), FilePath -> Int64 -> IO ())
-mkIter ref = (iter, \f _ -> onF f iter)
+mkIter :: IORef L.ByteString
+       -> (Iteratee IO (), FilePath -> Int64 -> Int64 -> IO ())
+mkIter ref = (iter, \f st sz -> onF f st sz iter)
   where
     iter = do
         x <- copyingStream2stream
         liftIO $ modifyIORef ref $ \s -> L.append s (fromWrap x)
 
-    onF f i = enumFile f i >>= run
+    onF f st sz i = enumFilePartial f (st,st+sz) i >>= run
 
 
 testChunkOn1_0 :: Test
@@ -726,47 +747,68 @@
 
 testSendFile :: Test
 testSendFile = testCase "server/sendFile" $ do
-    tid <- forkIO $ httpServe "*" port "localhost"
-           Nothing Nothing $
-           runSnap sendFileFoo
-    waitabit
+    bracket (forkIO $ httpServe "*" port "localhost"
+                                Nothing Nothing
+                    $ runSnap sendFileFoo)
+            (killThread)
+            (\tid -> do
+                 m <- timeout (120 * seconds) $ go tid 
+                 maybe (assertFailure "timeout")
+                       (const $ return ())
+                       m)
 
-    rsp <- HTTP.simpleHTTP (HTTP.getRequest "http://localhost:8123/")
-    doc <- HTTP.getResponseBody rsp
+  where
+    go tid = do
+        waitabit
+        
+        rsp <- HTTP.simpleHTTP (HTTP.getRequest "http://localhost:8123/")
+        doc <- HTTP.getResponseBody rsp
+        
+        killThread tid
+        waitabit
+        
+        assertEqual "sendFile" "FOO\n" doc
 
-    killThread tid
-    waitabit
 
-    assertEqual "sendFile" "FOO\n" doc
-
-  where
     waitabit = threadDelay $ ((10::Int)^(6::Int))
+
     port     = 8123
     
 
 testServerStartupShutdown :: Test
 testServerStartupShutdown = testCase "server/startup/shutdown" $ do
-    tid <- forkIO $
-           httpServe "*"
-                     port
-                     "localhost"
-                     (Just "test-access.log")
-                     (Just "test-error.log")
-                     (runSnap pongServer)
-    waitabit
+    bracket (forkIO $
+             httpServe "*"
+                       port
+                       "localhost"
+                       (Just "test-access.log")
+                       (Just "test-error.log")
+                       (runSnap pongServer))
+            (killThread)
+            (\tid -> do
+                 m <- timeout (120 * seconds) $ go tid 
+                 maybe (assertFailure "timeout")
+                       (const $ return ())
+                       m)
 
-    rsp <- HTTP.simpleHTTP (HTTP.getRequest "http://localhost:8145/")
-    doc <- HTTP.getResponseBody rsp
-    assertEqual "server" "PONG" doc
 
-    killThread tid
-    waitabit
+  where
+    go tid = do
+        waitabit
 
-    expectException $ HTTP.simpleHTTP (HTTP.getRequest "http://localhost:8145/")
+        rsp <- HTTP.simpleHTTP (HTTP.getRequest "http://localhost:8145/")
+        doc <- HTTP.getResponseBody rsp
+        assertEqual "server" "PONG" doc
 
-    return ()
-  where
+        killThread tid
+        waitabit
+
+        expectException $ HTTP.simpleHTTP
+                        $ HTTP.getRequest "http://localhost:8145/"
+        return ()
+
     waitabit = threadDelay $ 2*((10::Int)^(6::Int))
+
     port = 8145
 
 
@@ -803,14 +845,21 @@
 
         putMVar result e
 
-    r <- takeMVar result
+    e <- timeout (75*seconds) $ takeMVar result
 
-    case r of
-      (Left (_::SomeException)) -> return ()
-      (Right _)                 -> assertFailure "socket didn't get killed"
+    case e of
+      Nothing  -> killThread tid >> assertFailure "timeout"
+      (Just r) ->
+          case r of
+            (Left (_::SomeException)) -> return ()
+            (Right _)                 -> assertFailure "socket didn't get killed"
 
 
   where
     waitabit = threadDelay $ 2*((10::Int)^(6::Int))
     port = 8146
 
+
+
+seconds :: Int
+seconds = (10::Int) ^ (6::Int)
diff --git a/test/suite/Test/Blackbox.hs b/test/suite/Test/Blackbox.hs
--- a/test/suite/Test/Blackbox.hs
+++ b/test/suite/Test/Blackbox.hs
@@ -20,6 +20,7 @@
 import             Network.Socket
 import qualified   Network.Socket.ByteString as N
 import             Prelude hiding (take)
+import             System.Timeout
 import             Test.Framework
 import             Test.Framework.Providers.HUnit
 import             Test.Framework.Providers.QuickCheck2
@@ -37,6 +38,7 @@
 
 tests :: Int -> [Test]
 tests port = map ($ port) [ testPong
+                          , testHeadPong
                           , testEcho
                           , testRot13
                           , testSlowLoris
@@ -71,12 +73,29 @@
     HTTP.getResponseBody rsp
 
 
+headPong :: Int -> IO String
+headPong port = do
+    let req = (HTTP.getRequest $ 
+               "http://localhost:" ++ show port ++ "/pong")
+                { HTTP.rqMethod = HTTP.HEAD }
+
+    rsp <- HTTP.simpleHTTP req
+
+    HTTP.getResponseBody rsp
+
+
 testPong :: Int -> Test
 testPong port = testCase "blackbox/pong" $ do
     doc <- doPong port
     assertEqual "pong response" "PONG" doc
 
 
+testHeadPong :: Int -> Test
+testHeadPong port = testCase "blackbox/pong/HEAD" $ do
+    doc <- headPong port
+    assertEqual "pong HEAD response" "" doc
+
+
 testEcho :: Int -> Test
 testEcho port = testProperty "blackbox/echo" $
                 monadicIO $ forAllM arbitrary prop
@@ -122,6 +141,12 @@
 
   where
     go sock = do
+        m <- timeout (120*seconds) $ go' sock
+        maybe (assertFailure "slowloris: timeout")
+              (const $ return ())
+              m
+
+    go' sock = do
         N.sendAll sock "POST /echo HTTP/1.1\r\n"
         N.sendAll sock "Host: 127.0.0.1\r\n"
         N.sendAll sock "Content-Length: 2500000\r\n"
@@ -140,46 +165,72 @@
 testBlockingRead :: Int -> Test
 testBlockingRead port = testCase "blackbox/testBlockingRead" $
                         withSock port $ \sock -> do
-    N.sendAll sock "GET /"
-    waitabit
-    N.sendAll sock "pong HTTP/1.1\r\n"
-    N.sendAll sock "Host: 127.0.0.1\r\n"
-    N.sendAll sock "Content-Length: 0\r\n"
-    N.sendAll sock "Connection: close\r\n\r\n"
+    m <- timeout (60*seconds) $ go sock
+    maybe (assertFailure "timeout")
+          (const $ return ())
+          m
 
-    resp <- recvAll sock
+  where
+    go sock = do
+        N.sendAll sock "GET /"
+        waitabit
+        N.sendAll sock "pong HTTP/1.1\r\n"
+        N.sendAll sock "Host: 127.0.0.1\r\n"
+        N.sendAll sock "Content-Length: 0\r\n"
+        N.sendAll sock "Connection: close\r\n\r\n"
 
-    let s = head $ ditchHeaders $ S.lines resp
+        resp <- recvAll sock
 
-    assertEqual "pong response" "PONG" s
+        let s = head $ ditchHeaders $ S.lines resp
 
+        assertEqual "pong response" "PONG" s
 
+
 -- test server's ability to trap/recover from IO errors
 testPartial :: Int -> Test
 testPartial port = testCase "blackbox/testPartial" $ do
-    withSock port $ \sock ->
-        N.sendAll sock "GET /pong HTTP/1.1\r\n"
+    m <- timeout (60*seconds) go
+    maybe (assertFailure "timeout")
+          (const $ return ())
+          m
 
-    doc <- doPong port
-    assertEqual "pong response" "PONG" doc
 
+  where
+    go = do
+        withSock port $ \sock ->
+            N.sendAll sock "GET /pong HTTP/1.1\r\n"
 
+        doc <- doPong port
+        assertEqual "pong response" "PONG" doc
+
+
 testBigResponse :: Int -> Test
 testBigResponse port = testCase "blackbox/testBigResponse" $
                        withSock port $ \sock -> do
-    N.sendAll sock "GET /bigresponse HTTP/1.1\r\n"
-    N.sendAll sock "Host: 127.0.0.1\r\n"
-    N.sendAll sock "Content-Length: 0\r\n"
-    N.sendAll sock "Connection: close\r\n\r\n"
+    m <- timeout (120*seconds) $ go sock
+    maybe (assertFailure "timeout")
+          (const $ return ())
+          m
+    
+  where
+    go sock = do
+        N.sendAll sock "GET /bigresponse HTTP/1.1\r\n"
+        N.sendAll sock "Host: 127.0.0.1\r\n"
+        N.sendAll sock "Content-Length: 0\r\n"
+        N.sendAll sock "Connection: close\r\n\r\n"
 
-    let body = S.replicate 4000000 '.'
-    resp <- recvAll sock
+        let body = S.replicate 4000000 '.'
+        resp <- recvAll sock
 
-    let s = head $ ditchHeaders $ S.lines resp
+        let s = head $ ditchHeaders $ S.lines resp
 
-    assertBool "big response" $ body == s
+        assertBool "big response" $ body == s
 
 
 ------------------------------------------------------------------------------
 waitabit :: IO ()
-waitabit = threadDelay $ 2*((10::Int)^(6::Int))
+waitabit = threadDelay $ 2*seconds
+
+
+seconds :: Int
+seconds = (10::Int) ^ (6::Int)
