Skip to content

Commit

Permalink
Move tests and rename error
Browse files Browse the repository at this point in the history
  • Loading branch information
marinelli committed Dec 18, 2024
1 parent 749ed45 commit 1e82860
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 35 deletions.
2 changes: 1 addition & 1 deletion http-client/Network/HTTP/Client/Headers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ parseStatusHeaders mhl mnh conn timeout' onEarlyHintHeaders cont
guardMaxNumberHeaders :: Int -> IO ()
guardMaxNumberHeaders count = case fmap unMaxNumberHeaders mnh of
Nothing -> pure ()
Just n -> when (count >= n) $ throwHttp TooManyHeaders
Just n -> when (count >= n) $ throwHttp TooManyHeaderFields

parseHeaders :: Int -> ([Header] -> [Header]) -> IO [Header]
parseHeaders count front = do
Expand Down
8 changes: 4 additions & 4 deletions http-client/Network/HTTP/Client/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ data HttpExceptionContent
--
-- @since 0.5.0
| OverlongHeaders
-- ^ Too many total bytes in a single header field were
-- returned by the server.
-- ^ Too many total bytes in the HTTP header were returned
-- by the server.
--
-- @since 0.5.0
| TooManyHeaders
-- ^ Too many header fields were returned by the server,
| TooManyHeaderFields
-- ^ Too many HTTP header fields were returned by the server.
--
-- @since 0.7.18
| ResponseTimeout
Expand Down
24 changes: 24 additions & 0 deletions http-client/test-nonet/Network/HTTP/ClientSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ notWindows _ = return ()
notWindows x = x
#endif

crlf :: S.ByteString
crlf = "\r\n"

main :: IO ()
main = hspec spec

Expand Down Expand Up @@ -323,3 +326,24 @@ spec = describe "Client" $ do
case parseRequest "https://o_O:18446744072699450606" of
Left _ -> pure () :: IO ()
Right req -> error $ "Invalid request: " ++ show req

it "too many header fields" $ do
let message = S.concat $
["HTTP/1.1 200 OK", crlf] <> replicate 120 ("foo: bar" <> crlf) <> [crlf, "body"]

serveWith message $ \port -> do
man <- newManager $ managerSetMaxNumberHeaders 120 defaultManagerSettings
req <- parseUrlThrow $ "http://127.0.0.1:" ++ show port
httpLbs req man `shouldThrow` \e -> case e of
HttpExceptionRequest _ TooManyHeaderFields -> True
_otherwise -> False

it "not too many header fields" $ do
let message = S.concat $
["HTTP/1.1 200 OK", crlf] <> replicate 120 ("foo: bar" <> crlf) <> [crlf, "body"]

serveWith message $ \port -> do
man <- newManager $ managerSetMaxNumberHeaders 121 defaultManagerSettings
req <- parseUrlThrow $ "http://127.0.0.1:" ++ show port
res <- httpLbs req man
responseBody res `shouldBe` "body"
1 change: 1 addition & 0 deletions http-conduit/Network/HTTP/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import qualified Data.Aeson as A

import qualified Data.Traversable as T
import Control.Exception (throw, throwIO, Exception)
import Data.Monoid
import Data.Typeable (Typeable)
import qualified Data.Conduit as C
import Data.Conduit (runConduit, (.|), ConduitM)
Expand Down
31 changes: 1 addition & 30 deletions http-conduit/test/main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import qualified Data.ByteString.Lazy.Char8 as L8
import Test.HUnit
import Network.Wai hiding (requestBody)
import Network.Wai.Conduit (responseSource, sourceRequestBody)
import Network.HTTP.Client (streamFile, defaultManagerSettings)
import Network.HTTP.Client.Internal (managerMaxNumberHeaders)
import Network.HTTP.Client (streamFile)
import System.IO.Temp (withSystemTempFile)
import qualified Network.Wai as Wai
import Network.Wai.Handler.Warp (runSettings, defaultSettings, setPort, setBeforeMainLoop, Settings, setTimeout)
Expand Down Expand Up @@ -56,7 +55,6 @@ import qualified Data.Aeson as A
import qualified Network.HTTP.Simple as Simple
import Data.Monoid (mempty)
import Control.Monad.Trans.Resource (runResourceT)
import Data.Maybe (fromJust)

past :: UTCTime
past = UTCTime (ModifiedJulianDay 56200) (secondsToDiffTime 0)
Expand Down Expand Up @@ -263,18 +261,6 @@ main = do
let Just req1 = parseUrlThrow $ "http://127.0.0.1:" ++ show port
_ <- httpLbs req1 manager
return ()
it "too many header fields" $ tooManyHeaderFields $ \port -> do
manager <- newManager tlsManagerSettings
let Just req1 = parseUrlThrow $ "http://127.0.0.1:" ++ show port
res1 <- try $ runResourceT $ http req1 manager
case res1 of
Left e -> show (e :: SomeException) @?= show (HttpExceptionRequest req1 TooManyHeaders)
_ -> error "Shouldn't have worked"
it "not too many header fields" $ notTooManyHeaderFields $ \port -> do
manager <- newManager tlsManagerSettings
let Just req1 = parseUrlThrow $ "http://127.0.0.1:" ++ show port
_ <- httpLbs req1 manager
return ()
describe "redirects" $ do
it "doesn't double escape" $ redir $ \port -> do
manager <- newManager tlsManagerSettings
Expand Down Expand Up @@ -539,21 +525,6 @@ notOverLongHeaders = withCApp $ \app' -> do
where
src = sourceList $ [S.concat $ "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 16384\r\n\r\n" : ( take 16384 $ repeat "x")]

tooManyHeaderFields :: (Int -> IO ()) -> IO ()
tooManyHeaderFields =
withCApp $ \app' -> runConduit $ src .| appSink app'
where
limit = fromEnum (fromJust $ managerMaxNumberHeaders defaultManagerSettings)
src = sourceList $ "HTTP/1.0 200 OK\r\n" : replicate limit "foo: bar\r\n"

notTooManyHeaderFields :: (Int -> IO ()) -> IO ()
notTooManyHeaderFields = withCApp $ \app' -> do
runConduit $ appSource app' .| CL.drop 1
runConduit $ src .| appSink app'
where
limit = fromEnum (fromJust $ managerMaxNumberHeaders defaultManagerSettings) - 1
src = sourceList $ ["HTTP/1.0 200 OK\r\n"] <> replicate limit "foo: bar\r\n" <> ["\r\n"]

redir :: (Int -> IO ()) -> IO ()
redir =
withApp' redirApp
Expand Down

0 comments on commit 1e82860

Please sign in to comment.