@@ -39,6 +39,7 @@ module Network.Wai.Handler.Warp
3939 , InvalidRequest (..)
4040#if TEST
4141 , takeHeaders
42+ , readInt
4243#endif
4344 ) where
4445
@@ -299,7 +300,7 @@ sendResponse :: T.Handle
299300 -> Request -> H.HttpVersion -> Socket -> Response -> IO Bool
300301sendResponse th req hv socket (ResponseFile s hs fp mpart) = do
301302 (hs', cl) <-
302− case (mcl, mpart) of
303+ case (readInt `fmap` lookup "content-length" hs, mpart) of
303304 (Just cl, _) -> return (hs, cl)
304305 (Nothing, Nothing) -> do
305306 cl <- P.fileSize `fmap` P.getFileStatus fp
@@ -322,14 +323,6 @@ sendResponse th req hv socket (ResponseFile s hs fp mpart) = do
322323 T.tickle th
323324 return True
324325 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
333326sendResponse th req hv socket (ResponseBuilder s hs b)
334327 | hasBody s req = do
335328 toByteStringIO (\bs -> do
@@ -519,3 +512,8 @@ checkCR bs pos =
519512 then p
520513 else pos
521514{-# INLINE checkCR #-}
515+
516+-- Note: This function produces garbage on invalid input. But serving an
517+-- invalid content-length is a bad idea, mkay?
518+readInt :: S.ByteString -> Integer
519+readInt = S.foldl' (\x w -> x * 10 + fromIntegral w - 48) 0