diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,9 @@
+## 3.3.8
+
+* Maximum header size is configurable.
+  [#781](https://github.com/yesodweb/wai/pull/781)
+* Ignoring an exception from shutdown (gracefulClose).
+
 ## 3.3.7
 
 * InvalidArgument (Bad file descriptor) is ignored in `receive`.
diff --git a/Network/Wai/Handler/Warp.hs b/Network/Wai/Handler/Warp.hs
--- a/Network/Wai/Handler/Warp.hs
+++ b/Network/Wai/Handler/Warp.hs
@@ -74,6 +74,7 @@
   , setGracefulShutdownTimeout
   , setGracefulCloseTimeout1
   , setGracefulCloseTimeout2
+  , setMaxTotalHeaderLength
     -- ** Getters
   , getPort
   , getHost
@@ -123,7 +124,7 @@
   , defaultPushPromise
   ) where
 
-import Control.Exception (SomeException, throwIO, throw)
+import Control.Exception (SomeException, throwIO)
 import Data.Streaming.Network (HostPreference)
 import qualified Data.Vault.Lazy as Vault
 import Data.X509
@@ -435,6 +436,13 @@
 setGracefulShutdownTimeout :: Maybe Int
                            -> Settings -> Settings
 setGracefulShutdownTimeout time y = y { settingsGracefulShutdownTimeout = time }
+
+-- | Set the maximum header size that Warp will tolerate when using HTTP/1.x.
+--
+-- Since 3.3.8
+setMaxTotalHeaderLength :: Int -> Settings -> Settings
+setMaxTotalHeaderLength maxTotalHeaderLength settings = settings
+  { settingsMaxTotalHeaderLength = maxTotalHeaderLength }
 
 -- | Explicitly pause the slowloris timeout.
 --
diff --git a/Network/Wai/Handler/Warp/Request.hs b/Network/Wai/Handler/Warp/Request.hs
--- a/Network/Wai/Handler/Warp/Request.hs
+++ b/Network/Wai/Handler/Warp/Request.hs
@@ -38,13 +38,7 @@
 import Network.Wai.Handler.Warp.Imports hiding (readInt, lines)
 import Network.Wai.Handler.Warp.ReadInt
 import Network.Wai.Handler.Warp.RequestHeader
-import Network.Wai.Handler.Warp.Settings (Settings, settingsNoParsePath)
-
-----------------------------------------------------------------
-
--- FIXME come up with good values here
-maxTotalHeaderLength :: Int
-maxTotalHeaderLength = 50 * 1024
+import Network.Wai.Handler.Warp.Settings (Settings, settingsNoParsePath, settingsMaxTotalHeaderLength)
 
 ----------------------------------------------------------------
 
@@ -68,7 +62,7 @@
             -- Body producing action used for flushing the request body
 
 recvRequest firstRequest settings conn ii th addr src transport = do
-    hdrlines <- headerLines firstRequest src
+    hdrlines <- headerLines (settingsMaxTotalHeaderLength settings) firstRequest src
     (method, unparsedPath, path, query, httpversion, hdr) <- parseHeaderLines hdrlines
     let idxhdr = indexRequestHeader hdr
         expect = idxhdr ! fromEnum ReqExpect
@@ -107,8 +101,8 @@
 
 ----------------------------------------------------------------
 
-headerLines :: Bool -> Source -> IO [ByteString]
-headerLines firstRequest src = do
+headerLines :: Int -> Bool -> Source -> IO [ByteString]
+headerLines maxTotalHeaderLength firstRequest src = do
     bs <- readSource src
     if S.null bs
         -- When we're working on a keep-alive connection and trying to
@@ -116,7 +110,7 @@
         -- lack of data as a real exception. See the http1 function in
         -- the Run module for more details.
         then if firstRequest then throwIO ConnectionClosedByPeer else throwIO NoKeepAliveRequest
-        else push src (THStatus 0 id id) bs
+        else push maxTotalHeaderLength src (THStatus 0 id id) bs
 
 data NoKeepAliveRequest = NoKeepAliveRequest
     deriving (Show, Typeable)
@@ -226,8 +220,8 @@
 close = throwIO IncompleteHeaders
 -}
 
-push :: Source -> THStatus -> ByteString -> IO [ByteString]
-push src (THStatus len lines prepend) bs'
+push :: Int -> Source -> THStatus -> ByteString -> IO [ByteString]
+push maxTotalHeaderLength src (THStatus len lines prepend) bs'
         -- Too many bytes
         | len > maxTotalHeaderLength = throwIO OverLargeHeader
         | otherwise = push' mnl
@@ -255,13 +249,13 @@
     push' Nothing = do
         bst <- readSource' src
         when (S.null bst) $ throwIO IncompleteHeaders
-        push src status bst
+        push maxTotalHeaderLength src status bst
       where
         len' = len + bsLen
         prepend' = S.append bs
         status = THStatus len' lines prepend'
     -- Found a newline, but next line continues as a multiline header
-    push' (Just (end, True)) = push src status rest
+    push' (Just (end, True)) = push maxTotalHeaderLength src status rest
       where
         rest = S.drop (end + 1) bs
         prepend' = S.append (SU.unsafeTake (checkCR bs end) bs)
@@ -280,12 +274,12 @@
                       in if start < bsLen then
                              -- more bytes in this chunk, push again
                              let bs'' = SU.unsafeDrop start bs
-                              in push src status bs''
+                              in push maxTotalHeaderLength src status bs''
                            else do
                              -- no more bytes in this chunk, ask for more
                              bst <- readSource' src
                              when (S.null bs) $ throwIO IncompleteHeaders
-                             push src status bst
+                             push maxTotalHeaderLength src status bst
       where
         start = end + 1 -- start of next chunk
         line = SU.unsafeTake (checkCR bs end) bs
diff --git a/Network/Wai/Handler/Warp/Run.hs b/Network/Wai/Handler/Warp/Run.hs
--- a/Network/Wai/Handler/Warp/Run.hs
+++ b/Network/Wai/Handler/Warp/Run.hs
@@ -76,7 +76,7 @@
             if tm == 0 then
                 close s
               else
-                gracefulClose s tm
+                gracefulClose s tm `E.catch` \(E.SomeException _) -> return ()
 #else
       , connClose = close s
 #endif
diff --git a/Network/Wai/Handler/Warp/Settings.hs b/Network/Wai/Handler/Warp/Settings.hs
--- a/Network/Wai/Handler/Warp/Settings.hs
+++ b/Network/Wai/Handler/Warp/Settings.hs
@@ -128,6 +128,10 @@
       -- Default: 2000.
       --
       -- Since 3.3.5
+    , settingsMaxTotalHeaderLength :: Int
+      -- ^ Determines the maximum header size that Warp will tolerate when using HTTP/1.x.
+      -- 
+      -- Since 3.3.8
     }
 
 -- | Specify usage of the PROXY protocol.
@@ -166,6 +170,7 @@
     , settingsGracefulShutdownTimeout = Nothing
     , settingsGracefulCloseTimeout1 = 0
     , settingsGracefulCloseTimeout2 = 2000
+    , settingsMaxTotalHeaderLength = 50 * 1024
     }
 
 -- | Apply the logic provided by 'defaultOnException' to determine if an
diff --git a/test/RequestSpec.hs b/test/RequestSpec.hs
--- a/test/RequestSpec.hs
+++ b/test/RequestSpec.hs
@@ -7,6 +7,7 @@
 import Network.Wai.Handler.Warp.File (parseByteRanges)
 import Network.Wai.Handler.Warp.Request
 import Network.Wai.Handler.Warp.Types
+import Network.Wai.Handler.Warp.Settings (settingsMaxTotalHeaderLength, defaultSettings)
 import Test.Hspec
 import Test.Hspec.QuickCheck
 import qualified Data.ByteString as S
@@ -17,6 +18,9 @@
 main :: IO ()
 main = hspec spec
 
+defaultMaxTotalHeaderLength :: Int
+defaultMaxTotalHeaderLength = settingsMaxTotalHeaderLength defaultSettings
+
 spec :: Spec
 spec = do
   describe "headerLines" $ do
@@ -63,29 +67,29 @@
   describe "headerLines" $ do
       it "can handle a nomarl case" $ do
           src <- mkSourceFunc ["Status: 200\r\nContent-Type: text/plain\r\n\r\n"] >>= mkSource
-          x <- headerLines True src
+          x <- headerLines defaultMaxTotalHeaderLength True src
           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
 
       it "can handle a nasty case (1)" $ do
           src <- mkSourceFunc ["Status: 200", "\r\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource
-          x <- headerLines True src
+          x <- headerLines defaultMaxTotalHeaderLength True src
           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
 
       it "can handle a nasty case (1)" $ do
           src <- mkSourceFunc ["Status: 200", "\r", "\nContent-Type: text/plain", "\r", "\n\r\n"] >>= mkSource
-          x <- headerLines True src
+          x <- headerLines defaultMaxTotalHeaderLength True src
           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
 
       it "can handle a nasty case (1)" $ do
           src <- mkSourceFunc ["Status: 200", "\r", "\n", "Content-Type: text/plain", "\r", "\n", "\r", "\n"] >>= mkSource
-          x <- headerLines True src
+          x <- headerLines defaultMaxTotalHeaderLength True src
           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
 
       it "can handle an illegal case (1)" $ do
           src <- mkSourceFunc ["\nStatus:", "\n 200", "\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource
-          x <- headerLines True src
+          x <- headerLines defaultMaxTotalHeaderLength True src
           x `shouldBe` []
-          y <- headerLines True src
+          y <- headerLines defaultMaxTotalHeaderLength True src
           y `shouldBe` ["Status: 200", "Content-Type: text/plain"]
 
   where
@@ -111,7 +115,7 @@
                     writeIORef ref z
                     return y
     src' <- mkSource src
-    res <- headerLines True src'
+    res <- headerLines defaultMaxTotalHeaderLength True src'
     return (res, src')
 
 consumeLen :: Int -> Source -> IO S8.ByteString
diff --git a/warp.cabal b/warp.cabal
--- a/warp.cabal
+++ b/warp.cabal
@@ -1,5 +1,5 @@
 Name:                warp
-Version:             3.3.7
+Version:             3.3.8
 Synopsis:            A fast, light-weight web server for WAI applications.
 License:             MIT
 License-file:        LICENSE
