on master help sign in
More efficient takeInt
commitf6134fa15519272e6f3f424f36464ed754e407a5 authorMichael Snoyman <michael@snoyman.com> dateWed 22 Jun 2011, 11:00 (15 years ago) parenta7e4a7d
2 files changed+13−10
Network/Wai/Handler/Warp.hs+7−9 runtests.hs+6−1
Network/Wai/Handler/Warp.hs+7−9
@@ -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
runtests.hs+6−1
@@ -3,11 +3,13 @@
33{-# LANGUAGE OverloadedStrings #-}
44import Test.Framework (defaultMain, testGroup, Test)
55import Test.Framework.Providers.HUnit
6+import Test.Framework.Providers.QuickCheck2
67import Test.HUnit hiding (Test)
78
8−import Network.Wai.Handler.Warp (takeHeaders, InvalidRequest (..))
9+import Network.Wai.Handler.Warp (takeHeaders, InvalidRequest (..), readInt)
910import Data.Enumerator (run_, ($$), enumList, run)
1011import Control.Exception (fromException)
12+import qualified Data.ByteString.Char8 as S8
1113
1214main :: IO ()
1315main = defaultMain [testSuite]
@@ -17,6 +19,9 @@ testSuite = testGroup "Text.Hamlet"
1719 [ testCase "takeUntilBlank safe" caseTakeUntilBlankSafe
1820 , testCase "takeUntilBlank too many lines" caseTakeUntilBlankTooMany
1921 , testCase "takeUntilBlank too large" caseTakeUntilBlankTooLarge
22+ , testProperty "takeInt" $ \i' ->
23+ let i = abs i'
24+ in i == readInt (S8.pack $ show i)
2025 ]
2126
2227caseTakeUntilBlankSafe = do