    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Network.HTTP.Headers
    -- Copyright   :  See LICENSE file
    -- License     :  BSD
    --
    -- Maintainer  :  Ganesh Sittampalam <ganesh@earth.li>
    -- Stability   :  experimental
    -- Portability :  non-portable (not tested)
    --
    -- This module provides the data types for representing HTTP headers, and
    -- operations for looking up header values and working with sequences of
    -- header values in 'Request's and 'Response's. To avoid having to provide
    -- separate set of operations for doing so, we introduce a type class 'HasHeaders'
    -- to facilitate writing such processing using overloading instead.
    --
    -----------------------------------------------------------------------------
    module Network.HTTP.Headers
       ( HasHeaders(..)     -- type class

       , Header(..)
       , mkHeader           -- :: HeaderName -> String -> Header
       , hdrName            -- :: Header     -> HeaderName
       , hdrValue           -- :: Header     -> String

       , HeaderName(..)

       , insertHeader          -- :: HasHeaders a => HeaderName -> String -> a -> a
       , insertHeaderIfMissing -- :: HasHeaders a => HeaderName -> String -> a -> a
       , insertHeaders         -- :: HasHeaders a => [Header] -> a -> a
       , retrieveHeaders       -- :: HasHeaders a => HeaderName -> a -> [Header]
       , replaceHeader         -- :: HasHeaders a => HeaderName -> String -> a -> a
       , findHeader            -- :: HasHeaders a => HeaderName -> a -> Maybe String
       , lookupHeader          -- :: HeaderName -> [Header] -> Maybe String

       , parseHeader           -- :: parseHeader :: String -> Result Header
       , parseHeaders          -- :: [String] -> Result [Header]

       , headerMap             -- :: [(String, HeaderName)]

       , HeaderSetter
       ) where

    import Data.Char (toLower)
    import Network.Stream (Result, failParse)
    import Network.HTTP.Utils ( trim, split, crlf )

    -- | The @Header@ data type pairs header names & values.
    data Header = Header HeaderName String

    hdrName :: Header -> HeaderName
    hdrName :: Header -> HeaderName
    hdrName (Header HeaderName
    h [Char]
    _) = HeaderName
    h

    hdrValue :: Header -> String
    hdrValue :: Header -> [Char]
    hdrValue (Header HeaderName
    _ [Char]
    v) = [Char]
    v

    -- | Header constructor as a function, hiding above rep.
    mkHeader :: HeaderName -> String -> Header
    mkHeader :: HeaderName -> [Char] -> Header
    mkHeader = HeaderName -> [Char] -> Header
    Header

    instance Show Header where
        show :: Header -> [Char]
    show (Header HeaderName
    key [Char]
    value) = HeaderName -> ShowS
    forall a. Show a => a -> ShowS
    shows HeaderName
    key (Char
    ':'Char -> ShowS
    forall a. a -> [a] -> [a]
    :Char
    ' 'Char -> ShowS
    forall a. a -> [a] -> [a]
    :[Char]
    value [Char] -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    crlf)

    -- | HTTP @HeaderName@ type, a Haskell data constructor for each
    -- specification-defined header, prefixed with @Hdr@ and CamelCased,
    -- (i.e., eliding the @-@ in the process.) Should you require using
    -- a custom header, there's the @HdrCustom@ constructor which takes
    -- a @String@ argument.
    --
    -- Encoding HTTP header names differently, as Strings perhaps, is an
    -- equally fine choice..no decidedly clear winner, but let's stick
    -- with data constructors here.
    --
    data HeaderName
        -- Generic Headers --
     = HdrCacheControl
     | HdrConnection
     | HdrDate
     | HdrPragma
     | HdrTransferEncoding
     | HdrUpgrade
     | HdrVia
        -- Request Headers --
     | HdrAccept
     | HdrAcceptCharset
     | HdrAcceptEncoding
     | HdrAcceptLanguage
     | HdrAuthorization
     | HdrCookie
     | HdrExpect
     | HdrFrom
     | HdrHost
     | HdrIfModifiedSince
     | HdrIfMatch
     | HdrIfNoneMatch
     | HdrIfRange
     | HdrIfUnmodifiedSince
     | HdrMaxForwards
     | HdrProxyAuthorization
     | HdrRange
     | HdrReferer
     | HdrUserAgent
        -- Response Headers
     | HdrAge
     | HdrLocation
     | HdrProxyAuthenticate
     | HdrPublic
     | HdrRetryAfter
     | HdrServer
     | HdrSetCookie
     | HdrTE
     | HdrTrailer
     | HdrVary
     | HdrWarning
     | HdrWWWAuthenticate
        -- Entity Headers
     | HdrAllow
     | HdrContentBase
     | HdrContentEncoding
     | HdrContentLanguage
     | HdrContentLength
     | HdrContentLocation
     | HdrContentMD5
     | HdrContentRange
     | HdrContentType
     | HdrETag
     | HdrExpires
     | HdrLastModified
        -- | MIME entity headers (for sub-parts)
     | HdrContentTransferEncoding
        -- | Allows for unrecognised or experimental headers.
     | HdrCustom String -- not in header map below.

    instance Eq HeaderName where
        HdrCustom [Char]
    a                == :: HeaderName -> HeaderName -> Bool
    == HdrCustom [Char]
    b                = ((Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> Char
    toLower [Char]
    a) [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == ((Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> Char
    toLower [Char]
    b)
        HeaderName
    HdrCacheControl            == HeaderName
    HdrCacheControl            = Bool
    True
        HeaderName
    HdrCacheControl            == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrCacheControl            = Bool
    False
        HeaderName
    HdrConnection              == HeaderName
    HdrConnection              = Bool
    True
        HeaderName
    HdrConnection              == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrConnection              = Bool
    False
        HeaderName
    HdrDate                    == HeaderName
    HdrDate                    = Bool
    True
        HeaderName
    HdrDate                    == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrDate                    = Bool
    False
        HeaderName
    HdrPragma                  == HeaderName
    HdrPragma                  = Bool
    True
        HeaderName
    HdrPragma                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrPragma                  = Bool
    False
        HeaderName
    HdrTransferEncoding        == HeaderName
    HdrTransferEncoding        = Bool
    True
        HeaderName
    HdrTransferEncoding        == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrTransferEncoding        = Bool
    False
        HeaderName
    HdrUpgrade                 == HeaderName
    HdrUpgrade                 = Bool
    True
        HeaderName
    HdrUpgrade                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrUpgrade                 = Bool
    False
        HeaderName
    HdrVia                     == HeaderName
    HdrVia                     = Bool
    True
        HeaderName
    HdrVia                     == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrVia                     = Bool
    False
        HeaderName
    HdrAccept                  == HeaderName
    HdrAccept                  = Bool
    True
        HeaderName
    HdrAccept                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAccept                  = Bool
    False
        HeaderName
    HdrAcceptCharset           == HeaderName
    HdrAcceptCharset           = Bool
    True
        HeaderName
    HdrAcceptCharset           == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAcceptCharset           = Bool
    False
        HeaderName
    HdrAcceptEncoding          == HeaderName
    HdrAcceptEncoding          = Bool
    True
        HeaderName
    HdrAcceptEncoding          == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAcceptEncoding          = Bool
    False
        HeaderName
    HdrAcceptLanguage          == HeaderName
    HdrAcceptLanguage          = Bool
    True
        HeaderName
    HdrAcceptLanguage          == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAcceptLanguage          = Bool
    False
        HeaderName
    HdrAuthorization           == HeaderName
    HdrAuthorization           = Bool
    True
        HeaderName
    HdrAuthorization           == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAuthorization           = Bool
    False
        HeaderName
    HdrCookie                  == HeaderName
    HdrCookie                  = Bool
    True
        HeaderName
    HdrCookie                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrCookie                  = Bool
    False
        HeaderName
    HdrExpect                  == HeaderName
    HdrExpect                  = Bool
    True
        HeaderName
    HdrExpect                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrExpect                  = Bool
    False
        HeaderName
    HdrFrom                    == HeaderName
    HdrFrom                    = Bool
    True
        HeaderName
    HdrFrom                    == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrFrom                    = Bool
    False
        HeaderName
    HdrHost                    == HeaderName
    HdrHost                    = Bool
    True
        HeaderName
    HdrHost                    == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrHost                    = Bool
    False
        HeaderName
    HdrIfModifiedSince         == HeaderName
    HdrIfModifiedSince         = Bool
    True
        HeaderName
    HdrIfModifiedSince         == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrIfModifiedSince         = Bool
    False
        HeaderName
    HdrIfMatch                 == HeaderName
    HdrIfMatch                 = Bool
    True
        HeaderName
    HdrIfMatch                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrIfMatch                 = Bool
    False
        HeaderName
    HdrIfNoneMatch             == HeaderName
    HdrIfNoneMatch             = Bool
    True
        HeaderName
    HdrIfNoneMatch             == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrIfNoneMatch             = Bool
    False
        HeaderName
    HdrIfRange                 == HeaderName
    HdrIfRange                 = Bool
    True
        HeaderName
    HdrIfRange                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrIfRange                 = Bool
    False
        HeaderName
    HdrIfUnmodifiedSince       == HeaderName
    HdrIfUnmodifiedSince       = Bool
    True
        HeaderName
    HdrIfUnmodifiedSince       == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrIfUnmodifiedSince       = Bool
    False
        HeaderName
    HdrMaxForwards             == HeaderName
    HdrMaxForwards             = Bool
    True
        HeaderName
    HdrMaxForwards             == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrMaxForwards             = Bool
    False
        HeaderName
    HdrProxyAuthorization      == HeaderName
    HdrProxyAuthorization      = Bool
    True
        HeaderName
    HdrProxyAuthorization      == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrProxyAuthorization      = Bool
    False
        HeaderName
    HdrRange                   == HeaderName
    HdrRange                   = Bool
    True
        HeaderName
    HdrRange                   == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrRange                   = Bool
    False
        HeaderName
    HdrReferer                 == HeaderName
    HdrReferer                 = Bool
    True
        HeaderName
    HdrReferer                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrReferer                 = Bool
    False
        HeaderName
    HdrUserAgent               == HeaderName
    HdrUserAgent               = Bool
    True
        HeaderName
    HdrUserAgent               == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrUserAgent               = Bool
    False
        HeaderName
    HdrAge                     == HeaderName
    HdrAge                     = Bool
    True
        HeaderName
    HdrAge                     == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAge                     = Bool
    False
        HeaderName
    HdrLocation                == HeaderName
    HdrLocation                = Bool
    True
        HeaderName
    HdrLocation                == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrLocation                = Bool
    False
        HeaderName
    HdrProxyAuthenticate       == HeaderName
    HdrProxyAuthenticate       = Bool
    True
        HeaderName
    HdrProxyAuthenticate       == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrProxyAuthenticate       = Bool
    False
        HeaderName
    HdrPublic                  == HeaderName
    HdrPublic                  = Bool
    True
        HeaderName
    HdrPublic                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrPublic                  = Bool
    False
        HeaderName
    HdrRetryAfter              == HeaderName
    HdrRetryAfter              = Bool
    True
        HeaderName
    HdrRetryAfter              == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrRetryAfter              = Bool
    False
        HeaderName
    HdrServer                  == HeaderName
    HdrServer                  = Bool
    True
        HeaderName
    HdrServer                  == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrServer                  = Bool
    False
        HeaderName
    HdrSetCookie               == HeaderName
    HdrSetCookie               = Bool
    True
        HeaderName
    HdrSetCookie               == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrSetCookie               = Bool
    False
        HeaderName
    HdrTE                      == HeaderName
    HdrTE                      = Bool
    True
        HeaderName
    HdrTE                      == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrTE                      = Bool
    False
        HeaderName
    HdrTrailer                 == HeaderName
    HdrTrailer                 = Bool
    True
        HeaderName
    HdrTrailer                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrTrailer                 = Bool
    False
        HeaderName
    HdrVary                    == HeaderName
    HdrVary                    = Bool
    True
        HeaderName
    HdrVary                    == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrVary                    = Bool
    False
        HeaderName
    HdrWarning                 == HeaderName
    HdrWarning                 = Bool
    True
        HeaderName
    HdrWarning                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrWarning                 = Bool
    False
        HeaderName
    HdrWWWAuthenticate         == HeaderName
    HdrWWWAuthenticate         = Bool
    True
        HeaderName
    HdrWWWAuthenticate         == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrWWWAuthenticate         = Bool
    False
        HeaderName
    HdrAllow                   == HeaderName
    HdrAllow                   = Bool
    True
        HeaderName
    HdrAllow                   == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrAllow                   = Bool
    False
        HeaderName
    HdrContentBase             == HeaderName
    HdrContentBase             = Bool
    True
        HeaderName
    HdrContentBase             == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentBase             = Bool
    False
        HeaderName
    HdrContentEncoding         == HeaderName
    HdrContentEncoding         = Bool
    True
        HeaderName
    HdrContentEncoding         == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentEncoding         = Bool
    False
        HeaderName
    HdrContentLanguage         == HeaderName
    HdrContentLanguage         = Bool
    True
        HeaderName
    HdrContentLanguage         == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentLanguage         = Bool
    False
        HeaderName
    HdrContentLength           == HeaderName
    HdrContentLength           = Bool
    True
        HeaderName
    HdrContentLength           == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentLength           = Bool
    False
        HeaderName
    HdrContentLocation         == HeaderName
    HdrContentLocation         = Bool
    True
        HeaderName
    HdrContentLocation         == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentLocation         = Bool
    False
        HeaderName
    HdrContentMD5              == HeaderName
    HdrContentMD5              = Bool
    True
        HeaderName
    HdrContentMD5              == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentMD5              = Bool
    False
        HeaderName
    HdrContentRange            == HeaderName
    HdrContentRange            = Bool
    True
        HeaderName
    HdrContentRange            == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentRange            = Bool
    False
        HeaderName
    HdrContentType             == HeaderName
    HdrContentType             = Bool
    True
        HeaderName
    HdrContentType             == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentType             = Bool
    False
        HeaderName
    HdrETag                    == HeaderName
    HdrETag                    = Bool
    True
        HeaderName
    HdrETag                    == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrETag                    = Bool
    False
        HeaderName
    HdrExpires                 == HeaderName
    HdrExpires                 = Bool
    True
        HeaderName
    HdrExpires                 == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrExpires                 = Bool
    False
        HeaderName
    HdrLastModified            == HeaderName
    HdrLastModified            = Bool
    True
        HeaderName
    HdrLastModified            == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrLastModified            = Bool
    False
        HeaderName
    HdrContentTransferEncoding == HeaderName
    HdrContentTransferEncoding = Bool
    True
        HeaderName
    HdrContentTransferEncoding == HeaderName
    _                          = Bool
    False
        HeaderName
    _                          == HeaderName
    HdrContentTransferEncoding = Bool
    False

    -- | @headerMap@ is a straight assoc list for translating between header names
    -- and values.
    headerMap :: [ (String,HeaderName) ]
    headerMap :: [([Char], HeaderName)]
    headerMap =
       [ [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Cache-Control"        HeaderName
    HdrCacheControl
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Connection"           HeaderName
    HdrConnection
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Date"                 HeaderName
    HdrDate
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Pragma"               HeaderName
    HdrPragma
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Transfer-Encoding"    HeaderName
    HdrTransferEncoding
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Upgrade"              HeaderName
    HdrUpgrade
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Via"                  HeaderName
    HdrVia
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Accept"               HeaderName
    HdrAccept
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Accept-Charset"       HeaderName
    HdrAcceptCharset
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Accept-Encoding"      HeaderName
    HdrAcceptEncoding
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Accept-Language"      HeaderName
    HdrAcceptLanguage
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Authorization"        HeaderName
    HdrAuthorization
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Cookie"               HeaderName
    HdrCookie
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Expect"               HeaderName
    HdrExpect
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "From"                 HeaderName
    HdrFrom
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Host"                 HeaderName
    HdrHost
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "If-Modified-Since"    HeaderName
    HdrIfModifiedSince
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "If-Match"             HeaderName
    HdrIfMatch
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "If-None-Match"        HeaderName
    HdrIfNoneMatch
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "If-Range"             HeaderName
    HdrIfRange
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "If-Unmodified-Since"  HeaderName
    HdrIfUnmodifiedSince
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Max-Forwards"         HeaderName
    HdrMaxForwards
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Proxy-Authorization"  HeaderName
    HdrProxyAuthorization
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Range"                HeaderName
    HdrRange
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Referer"              HeaderName
    HdrReferer
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "User-Agent"           HeaderName
    HdrUserAgent
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Age"                  HeaderName
    HdrAge
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Location"             HeaderName
    HdrLocation
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Proxy-Authenticate"   HeaderName
    HdrProxyAuthenticate
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Public"               HeaderName
    HdrPublic
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Retry-After"          HeaderName
    HdrRetryAfter
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Server"               HeaderName
    HdrServer
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Set-Cookie"           HeaderName
    HdrSetCookie
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "TE"                   HeaderName
    HdrTE
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Trailer"              HeaderName
    HdrTrailer
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Vary"                 HeaderName
    HdrVary
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Warning"              HeaderName
    HdrWarning
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "WWW-Authenticate"     HeaderName
    HdrWWWAuthenticate
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Allow"                HeaderName
    HdrAllow
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Base"         HeaderName
    HdrContentBase
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Encoding"     HeaderName
    HdrContentEncoding
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Language"     HeaderName
    HdrContentLanguage
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Length"       HeaderName
    HdrContentLength
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Location"     HeaderName
    HdrContentLocation
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-MD5"          HeaderName
    HdrContentMD5
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Range"        HeaderName
    HdrContentRange
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Type"         HeaderName
    HdrContentType
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "ETag"                 HeaderName
    HdrETag
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Expires"              HeaderName
    HdrExpires
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Last-Modified"        HeaderName
    HdrLastModified
       , [Char] -> HeaderName -> ([Char], HeaderName)
    forall {a} {b}. a -> b -> (a, b)
    p [Char]
    "Content-Transfer-Encoding" HeaderName
    HdrContentTransferEncoding
       ]
     where
      p :: a -> b -> (a, b)
    p a
    a b
    b = (a
    a,b
    b)

    instance Show HeaderName where
        show :: HeaderName -> [Char]
    show (HdrCustom [Char]
    s) = [Char]
    s
        show HeaderName
    x = case (([Char], HeaderName) -> Bool)
    -> [([Char], HeaderName)] -> [([Char], HeaderName)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((HeaderName -> HeaderName -> Bool
    forall a. Eq a => a -> a -> Bool
    ==HeaderName
    x)(HeaderName -> Bool)
    -> (([Char], HeaderName) -> HeaderName)
    -> ([Char], HeaderName)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .([Char], HeaderName) -> HeaderName
    forall a b. (a, b) -> b
    snd) [([Char], HeaderName)]
    headerMap of
                    [] -> ShowS
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "headerMap incomplete"
                    (([Char], HeaderName)
    h:[([Char], HeaderName)]
    _) -> ([Char], HeaderName) -> [Char]
    forall a b. (a, b) -> a
    fst ([Char], HeaderName)
    h

    -- | @HasHeaders@ is a type class for types containing HTTP headers, allowing
    -- you to write overloaded header manipulation functions
    -- for both 'Request' and 'Response' data types, for instance.
    class HasHeaders x where
        getHeaders :: x -> [Header]
        setHeaders :: x -> [Header] -> x

    -- Header manipulation functions

    type HeaderSetter a = HeaderName -> String -> a -> a

    -- | @insertHeader hdr val x@ inserts a header with the given header name
    -- and value. Does not check for existing headers with same name, allowing
    -- duplicates to be introduce (use 'replaceHeader' if you want to avoid this.)
    insertHeader :: HasHeaders a => HeaderSetter a
    insertHeader :: forall a. HasHeaders a => HeaderSetter a
    insertHeader HeaderName
    name [Char]
    value a
    x = a -> [Header] -> a
    forall x. HasHeaders x => x -> [Header] -> x
    setHeaders a
    x [Header]
    newHeaders
        where
            newHeaders :: [Header]
    newHeaders = (HeaderName -> [Char] -> Header
    Header HeaderName
    name [Char]
    value) Header -> [Header] -> [Header]
    forall a. a -> [a] -> [a]
    : a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    x

    -- | @insertHeaderIfMissing hdr val x@ adds the new header only if no previous
    -- header with name @hdr@ exists in @x@.
    insertHeaderIfMissing :: HasHeaders a => HeaderSetter a
    insertHeaderIfMissing :: forall a. HasHeaders a => HeaderSetter a
    insertHeaderIfMissing HeaderName
    name [Char]
    value a
    x = a -> [Header] -> a
    forall x. HasHeaders x => x -> [Header] -> x
    setHeaders a
    x ([Header] -> [Header]
    newHeaders ([Header] -> [Header]) -> [Header] -> [Header]
    forall a b. (a -> b) -> a -> b
    $ a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    x)
        where
            newHeaders :: [Header] -> [Header]
    newHeaders list :: [Header]
    list@(h :: Header
    h@(Header HeaderName
    n [Char]
    _): [Header]
    rest)
                | HeaderName
    n HeaderName -> HeaderName -> Bool
    forall a. Eq a => a -> a -> Bool
    == HeaderName
    name  = [Header]
    list
                | Bool
    otherwise  = Header
    h Header -> [Header] -> [Header]
    forall a. a -> [a] -> [a]
    : [Header] -> [Header]
    newHeaders [Header]
    rest
            newHeaders [] = [HeaderName -> [Char] -> Header
    Header HeaderName
    name [Char]
    value]

    -- | @replaceHeader hdr val o@ replaces the header @hdr@ with the
    -- value @val@, dropping any existing
    replaceHeader :: HasHeaders a => HeaderSetter a
    replaceHeader :: forall a. HasHeaders a => HeaderSetter a
    replaceHeader HeaderName
    name [Char]
    value a
    h = a -> [Header] -> a
    forall x. HasHeaders x => x -> [Header] -> x
    setHeaders a
    h [Header]
    newHeaders
        where
            newHeaders :: [Header]
    newHeaders = HeaderName -> [Char] -> Header
    Header HeaderName
    name [Char]
    value Header -> [Header] -> [Header]
    forall a. a -> [a] -> [a]
    : [ Header
    x | x :: Header
    x@(Header HeaderName
    n [Char]
    _) <- a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    h, HeaderName
    name HeaderName -> HeaderName -> Bool
    forall a. Eq a => a -> a -> Bool
    /= HeaderName
    n ]

    -- | @insertHeaders hdrs x@ appends multiple headers to @x@'s existing
    -- set.
    insertHeaders :: HasHeaders a => [Header] -> a -> a
    insertHeaders :: forall a. HasHeaders a => [Header] -> a -> a
    insertHeaders [Header]
    hdrs a
    x = a -> [Header] -> a
    forall x. HasHeaders x => x -> [Header] -> x
    setHeaders a
    x (a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    x [Header] -> [Header] -> [Header]
    forall a. [a] -> [a] -> [a]
    ++ [Header]
    hdrs)

    -- | @retrieveHeaders hdrNm x@ gets a list of headers with 'HeaderName' @hdrNm@.
    retrieveHeaders :: HasHeaders a => HeaderName -> a -> [Header]
    retrieveHeaders :: forall a. HasHeaders a => HeaderName -> a -> [Header]
    retrieveHeaders HeaderName
    name a
    x = (Header -> Bool) -> [Header] -> [Header]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Header -> Bool
    matchname (a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    x)
        where
            matchname :: Header -> Bool
    matchname (Header HeaderName
    n [Char]
    _) = HeaderName
    n HeaderName -> HeaderName -> Bool
    forall a. Eq a => a -> a -> Bool
    == HeaderName
    name

    -- | @findHeader hdrNm x@ looks up @hdrNm@ in @x@, returning the first
    -- header that matches, if any.
    findHeader :: HasHeaders a => HeaderName -> a -> Maybe String
    findHeader :: forall a. HasHeaders a => HeaderName -> a -> Maybe [Char]
    findHeader HeaderName
    n a
    x = HeaderName -> [Header] -> Maybe [Char]
    lookupHeader HeaderName
    n (a -> [Header]
    forall x. HasHeaders x => x -> [Header]
    getHeaders a
    x)

    -- | @lookupHeader hdr hdrs@ locates the first header matching @hdr@ in the
    -- list @hdrs@.
    lookupHeader :: HeaderName -> [Header] -> Maybe String
    lookupHeader :: HeaderName -> [Header] -> Maybe [Char]
    lookupHeader HeaderName
    _ [] = Maybe [Char]
    forall a. Maybe a
    Nothing
    lookupHeader HeaderName
    v (Header HeaderName
    n [Char]
    s:[Header]
    t)
      |  HeaderName
    v HeaderName -> HeaderName -> Bool
    forall a. Eq a => a -> a -> Bool
    == HeaderName
    n   =  [Char] -> Maybe [Char]
    forall a. a -> Maybe a
    Just [Char]
    s
      | Bool
    otherwise =  HeaderName -> [Header] -> Maybe [Char]
    lookupHeader HeaderName
    v [Header]
    t

    -- | @parseHeader headerNameAndValueString@ tries to unscramble a
    -- @header: value@ pairing and returning it as a 'Header'.
    parseHeader :: String -> Result Header
    parseHeader :: [Char] -> Result Header
    parseHeader [Char]
    str =
        case Char -> [Char] -> Maybe ([Char], [Char])
    forall a. Eq a => a -> [a] -> Maybe ([a], [a])
    split Char
    ':' [Char]
    str of
            Maybe ([Char], [Char])
    Nothing -> [Char] -> Result Header
    forall a. [Char] -> Result a
    failParse ([Char]
    "Unable to parse header: " [Char] -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ [Char]
    str)
            Just ([Char]
    k,[Char]
    v) -> Header -> Result Header
    forall a. a -> Either ConnError a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Header -> Result Header) -> Header -> Result Header
    forall a b. (a -> b) -> a -> b
    $ HeaderName -> [Char] -> Header
    Header ([Char] -> HeaderName
    fn [Char]
    k) (ShowS
    trim ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ Int -> ShowS
    forall a. Int -> [a] -> [a]
    drop Int
    1 [Char]
    v)
        where
            fn :: [Char] -> HeaderName
    fn [Char]
    k = case (([Char], HeaderName) -> HeaderName)
    -> [([Char], HeaderName)] -> [HeaderName]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Char], HeaderName) -> HeaderName
    forall a b. (a, b) -> b
    snd ([([Char], HeaderName)] -> [HeaderName])
    -> [([Char], HeaderName)] -> [HeaderName]
    forall a b. (a -> b) -> a -> b
    $ (([Char], HeaderName) -> Bool)
    -> [([Char], HeaderName)] -> [([Char], HeaderName)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ([Char] -> [Char] -> Bool
    match [Char]
    k ([Char] -> Bool)
    -> (([Char], HeaderName) -> [Char]) -> ([Char], HeaderName) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([Char], HeaderName) -> [Char]
    forall a b. (a, b) -> a
    fst) [([Char], HeaderName)]
    headerMap of
                     [] -> ([Char] -> HeaderName
    HdrCustom [Char]
    k)
                     (HeaderName
    h:[HeaderName]
    _) -> HeaderName
    h

            match :: String -> String -> Bool
            match :: [Char] -> [Char] -> Bool
    match [Char]
    s1 [Char]
    s2 = (Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower [Char]
    s1 [Char] -> [Char] -> Bool
    forall a. Eq a => a -> a -> Bool
    == (Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower [Char]
    s2

    -- | @parseHeaders hdrs@ takes a sequence of strings holding header
    -- information and parses them into a set of headers (preserving their
    -- order in the input argument.) Handles header values split up over
    -- multiple lines.
    parseHeaders :: [String] -> Result [Header]
    parseHeaders :: [[Char]] -> Result [Header]
    parseHeaders = [Header] -> [Result Header] -> Result [Header]
    forall a. [a] -> [Result a] -> Result [a]
    catRslts [] ([Result Header] -> Result [Header])
    -> ([[Char]] -> [Result Header]) -> [[Char]] -> Result [Header]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                     ([Char] -> Result Header) -> [[Char]] -> [Result Header]
    forall a b. (a -> b) -> [a] -> [b]
    map ([Char] -> Result Header
    parseHeader ([Char] -> Result Header) -> ShowS -> [Char] -> Result Header
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShowS
    clean) ([[Char]] -> [Result Header])
    -> ([[Char]] -> [[Char]]) -> [[Char]] -> [Result Header]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                         [Char] -> [[Char]] -> [[Char]]
    joinExtended [Char]
    ""
       where
            -- Joins consecutive lines where the second line
            -- begins with ' ' or '\t'.
            joinExtended :: [Char] -> [[Char]] -> [[Char]]
    joinExtended [Char]
    old      [] = [[Char]
    old]
            joinExtended [Char]
    old ([Char]
    h : [[Char]]
    t)
              | [Char] -> Bool
    isLineExtension [Char]
    h    = [Char] -> [[Char]] -> [[Char]]
    joinExtended ([Char]
    old [Char] -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Char
    ' ' Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    forall a. HasCallStack => [a] -> [a]
    tail [Char]
    h) [[Char]]
    t
              | Bool
    otherwise            = [Char]
    old [Char] -> [[Char]] -> [[Char]]
    forall a. a -> [a] -> [a]
    : [Char] -> [[Char]] -> [[Char]]
    joinExtended [Char]
    h [[Char]]
    t

            isLineExtension :: [Char] -> Bool
    isLineExtension (Char
    x:[Char]
    _) = Char
    x Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ' ' Bool -> Bool -> Bool
    || Char
    x Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '\t'
            isLineExtension [Char]
    _ = Bool
    False

            clean :: ShowS
    clean [] = []
            clean (Char
    h:[Char]
    t) | Char
    h Char -> [Char] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Char]
    "\t\r\n" = Char
    ' ' Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    clean [Char]
    t
                        | Bool
    otherwise = Char
    h Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    clean [Char]
    t

            -- tolerant of errors?  should parse
            -- errors here be reported or ignored?
            -- currently ignored.
            catRslts :: [a] -> [Result a] -> Result [a]
            catRslts :: forall a. [a] -> [Result a] -> Result [a]
    catRslts [a]
    list (Result a
    h:[Result a]
    t) =
                case Result a
    h of
                    Left ConnError
    _ -> [a] -> [Result a] -> Result [a]
    forall a. [a] -> [Result a] -> Result [a]
    catRslts [a]
    list [Result a]
    t
                    Right a
    v -> [a] -> [Result a] -> Result [a]
    forall a. [a] -> [Result a] -> Result [a]
    catRslts (a
    va -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :[a]
    list) [Result a]
    t
            catRslts [a]
    list [] = [a] -> Result [a]
    forall a b. b -> Either a b
    Right ([a] -> Result [a]) -> [a] -> Result [a]
    forall a b. (a -> b) -> a -> b
    $ [a] -> [a]
    forall a. [a] -> [a]
    reverse [a]
    list