@@ -81,6 +81,8 @@ import Blaze.ByteString.Builder.Char8 (fromChar, fromShow)
8181import Data.Monoid (mappend, mconcat)
8282import Network.Sendfile
8383
84+import qualified System.PosixCompat.Files as P
85+
8486import Control.Monad.IO.Class (liftIO)
8587import qualified Timeout as T
8688import Data.Word (Word8)
@@ -296,18 +298,38 @@ hasBody s req = s /= (H.Status 204 "") && requestMethod req /= "HEAD"
296298sendResponse :: T.Handle
297299 -> Request -> H.HttpVersion -> Socket -> Response -> IO Bool
298300sendResponse th req hv socket (ResponseFile s hs fp mpart) = do
299− Sock.sendMany socket $ L.toChunks $ toLazyByteString $ headers hv s hs False
301+ (hs', cl) <-
302+ case (mcl, mpart) of
303+ (Just cl, _) -> return (hs, cl)
304+ (Nothing, Nothing) -> do
305+ cl <- P.fileSize `fmap` P.getFileStatus fp
306+ return (("Content-Length", B.pack $ show cl):hs, fromIntegral cl)
307+ (Nothing, Just part) -> do
308+ let cl = filePartByteCount part
309+ return (("Content-Length", B.pack $ show cl):hs, fromIntegral cl)
310+ Sock.sendMany socket $ L.toChunks $ toLazyByteString $ headers hv s hs' False
300311 if hasBody s req
301312 then do
302313 case mpart of
303− Nothing -> sendfile socket fp EntireFile (T.tickle th)
314+ Nothing -> sendfile socket fp PartOfFile {
315+ rangeOffset = 0
316+ , rangeLength = cl
317+ } (T.tickle th)
304318 Just part -> sendfile socket fp PartOfFile {
305319 rangeOffset = filePartOffset part
306320 , rangeLength = filePartByteCount part
307321 } (T.tickle th)
308322 T.tickle th
309− return $ lookup "content-length" hs /= Nothing
323+ return True
310324 else return True
325+ where
326+ clS = lookup "content-length" hs
327+ mcl = clS >>= readInt
328+ -- FIXME make this more efficient
329+ readInt bs =
330+ case reads $ B.unpack bs of
331+ (i, _):_ -> Just i
332+ [] -> Nothing
311333sendResponse th req hv socket (ResponseBuilder s hs b)
312334 | hasBody s req = do
313335 toByteStringIO (\bs -> do