{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK hide, prune #-}
module Network.Http.Internal (
Hostname,
Port,
Request(..),
EntityBody(..),
ExpectMode(..),
Response(..),
StatusCode,
TransferEncoding(..),
ContentEncoding(..),
getStatusCode,
getStatusMessage,
getHeader,
Method(..),
Headers,
emptyHeaders,
updateHeader,
removeHeader,
buildHeaders,
lookupHeader,
retrieveHeaders,
HttpType (getHeaders),
HttpParseException(..),
composeRequestBytes,
composeResponseBytes
) where
import Prelude hiding (lookup)
import Blaze.ByteString.Builder (Builder)
import qualified Blaze.ByteString.Builder as Builder (copyByteString,
copyByteString,
fromByteString,
fromByteString,
toByteString)
import qualified Blaze.ByteString.Builder.Char8 as Builder (fromChar,
fromShow,
fromString)
import Control.Exception (Exception)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as S
import Data.CaseInsensitive (CI, mk, original)
import Data.HashMap.Strict (HashMap, delete, empty, foldrWithKey, insert,
insertWith, lookup, toList)
import Data.Int (Int64)
import Data.List (foldl')
import Data.Monoid (mconcat, mempty)
import Data.Typeable (Typeable)
import Data.Word (Word16)
type Hostname = ByteString
type Port = Word16
data Method
= GET
| HEAD
| POST
| PUT
| DELETE
| TRACE
| OPTIONS
| CONNECT
| PATCH
| Method ByteString
deriving (Int -> Method -> ShowS
[Method] -> ShowS
Method -> String
(Int -> Method -> ShowS)
-> (Method -> String) -> ([Method] -> ShowS) -> Show Method
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Method] -> ShowS
$cshowList :: [Method] -> ShowS
show :: Method -> String
$cshow :: Method -> String
showsPrec :: Int -> Method -> ShowS
$cshowsPrec :: Int -> Method -> ShowS
Show, ReadPrec [Method]
ReadPrec Method
Int -> ReadS Method
ReadS [Method]
(Int -> ReadS Method)
-> ReadS [Method]
-> ReadPrec Method
-> ReadPrec [Method]
-> Read Method
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Method]
$creadListPrec :: ReadPrec [Method]
readPrec :: ReadPrec Method
$creadPrec :: ReadPrec Method
readList :: ReadS [Method]
$creadList :: ReadS [Method]
readsPrec :: Int -> ReadS Method
$creadsPrec :: Int -> ReadS Method
Read, Eq Method
Eq Method =>
(Method -> Method -> Ordering)
-> (Method -> Method -> Bool)
-> (Method -> Method -> Bool)
-> (Method -> Method -> Bool)
-> (Method -> Method -> Bool)
-> (Method -> Method -> Method)
-> (Method -> Method -> Method)
-> Ord Method
Method -> Method -> Bool
Method -> Method -> Ordering
Method -> Method -> Method
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Method -> Method -> Method
$cmin :: Method -> Method -> Method
max :: Method -> Method -> Method
$cmax :: Method -> Method -> Method
>= :: Method -> Method -> Bool
$c>= :: Method -> Method -> Bool
> :: Method -> Method -> Bool
$c> :: Method -> Method -> Bool
<= :: Method -> Method -> Bool
$c<= :: Method -> Method -> Bool
< :: Method -> Method -> Bool
$c< :: Method -> Method -> Bool
compare :: Method -> Method -> Ordering
$ccompare :: Method -> Method -> Ordering
$cp1Ord :: Eq Method
Ord)
instance Eq Method where
GET == :: Method -> Method -> Bool
== GET = Bool
True
HEAD == HEAD = Bool
True
POST == POST = Bool
True
PUT == PUT = Bool
True
DELETE == DELETE = Bool
True
TRACE == TRACE = Bool
True
OPTIONS == OPTIONS = Bool
True
CONNECT == CONNECT = Bool
True
PATCH == PATCH = Bool
True
GET == Method "GET" = Bool
True
HEAD == Method "HEAD" = Bool
True
POST == Method "POST" = Bool
True
PUT == Method "PUT" = Bool
True
DELETE == Method "DELETE" = Bool
True
TRACE == Method "TRACE" = Bool
True
OPTIONS == Method "OPTIONS" = Bool
True
CONNECT == Method "CONNECT" = Bool
True
PATCH == Method "PATCH" = Bool
True
Method a :: ByteString
a == Method b :: ByteString
b = ByteString
a ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
b
m :: Method
m@(Method _) == other :: Method
other = Method
other Method -> Method -> Bool
forall a. Eq a => a -> a -> Bool
== Method
m
_ == _ = Bool
False
data Request
= Request {
Request -> Method
qMethod :: !Method,
Request -> Maybe ByteString
qHost :: !(Maybe ByteString),
Request -> ByteString
qPath :: !ByteString,
Request -> EntityBody
qBody :: !EntityBody,
Request -> ExpectMode
qExpect :: !ExpectMode,
:: !Headers
} deriving (Request -> Request -> Bool
(Request -> Request -> Bool)
-> (Request -> Request -> Bool) -> Eq Request
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Request -> Request -> Bool
$c/= :: Request -> Request -> Bool
== :: Request -> Request -> Bool
$c== :: Request -> Request -> Bool
Eq)
instance Show Request where
show :: Request -> String
show q :: Request
q = {-# SCC "Request.show" #-}
ByteString -> String
S.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ByteString -> ByteString
S.filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '\r') (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Builder -> ByteString
Builder.toByteString (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ Request -> ByteString -> Builder
composeRequestBytes Request
q "<default>"
data EntityBody = Empty | Chunking | Static Int64 deriving (Int -> EntityBody -> ShowS
[EntityBody] -> ShowS
EntityBody -> String
(Int -> EntityBody -> ShowS)
-> (EntityBody -> String)
-> ([EntityBody] -> ShowS)
-> Show EntityBody
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EntityBody] -> ShowS
$cshowList :: [EntityBody] -> ShowS
show :: EntityBody -> String
$cshow :: EntityBody -> String
showsPrec :: Int -> EntityBody -> ShowS
$cshowsPrec :: Int -> EntityBody -> ShowS
Show, EntityBody -> EntityBody -> Bool
(EntityBody -> EntityBody -> Bool)
-> (EntityBody -> EntityBody -> Bool) -> Eq EntityBody
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EntityBody -> EntityBody -> Bool
$c/= :: EntityBody -> EntityBody -> Bool
== :: EntityBody -> EntityBody -> Bool
$c== :: EntityBody -> EntityBody -> Bool
Eq, Eq EntityBody
Eq EntityBody =>
(EntityBody -> EntityBody -> Ordering)
-> (EntityBody -> EntityBody -> Bool)
-> (EntityBody -> EntityBody -> Bool)
-> (EntityBody -> EntityBody -> Bool)
-> (EntityBody -> EntityBody -> Bool)
-> (EntityBody -> EntityBody -> EntityBody)
-> (EntityBody -> EntityBody -> EntityBody)
-> Ord EntityBody
EntityBody -> EntityBody -> Bool
EntityBody -> EntityBody -> Ordering
EntityBody -> EntityBody -> EntityBody
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: EntityBody -> EntityBody -> EntityBody
$cmin :: EntityBody -> EntityBody -> EntityBody
max :: EntityBody -> EntityBody -> EntityBody
$cmax :: EntityBody -> EntityBody -> EntityBody
>= :: EntityBody -> EntityBody -> Bool
$c>= :: EntityBody -> EntityBody -> Bool
> :: EntityBody -> EntityBody -> Bool
$c> :: EntityBody -> EntityBody -> Bool
<= :: EntityBody -> EntityBody -> Bool
$c<= :: EntityBody -> EntityBody -> Bool
< :: EntityBody -> EntityBody -> Bool
$c< :: EntityBody -> EntityBody -> Bool
compare :: EntityBody -> EntityBody -> Ordering
$ccompare :: EntityBody -> EntityBody -> Ordering
$cp1Ord :: Eq EntityBody
Ord)
data ExpectMode = Normal | Continue deriving (Int -> ExpectMode -> ShowS
[ExpectMode] -> ShowS
ExpectMode -> String
(Int -> ExpectMode -> ShowS)
-> (ExpectMode -> String)
-> ([ExpectMode] -> ShowS)
-> Show ExpectMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExpectMode] -> ShowS
$cshowList :: [ExpectMode] -> ShowS
show :: ExpectMode -> String
$cshow :: ExpectMode -> String
showsPrec :: Int -> ExpectMode -> ShowS
$cshowsPrec :: Int -> ExpectMode -> ShowS
Show, ExpectMode -> ExpectMode -> Bool
(ExpectMode -> ExpectMode -> Bool)
-> (ExpectMode -> ExpectMode -> Bool) -> Eq ExpectMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExpectMode -> ExpectMode -> Bool
$c/= :: ExpectMode -> ExpectMode -> Bool
== :: ExpectMode -> ExpectMode -> Bool
$c== :: ExpectMode -> ExpectMode -> Bool
Eq, Eq ExpectMode
Eq ExpectMode =>
(ExpectMode -> ExpectMode -> Ordering)
-> (ExpectMode -> ExpectMode -> Bool)
-> (ExpectMode -> ExpectMode -> Bool)
-> (ExpectMode -> ExpectMode -> Bool)
-> (ExpectMode -> ExpectMode -> Bool)
-> (ExpectMode -> ExpectMode -> ExpectMode)
-> (ExpectMode -> ExpectMode -> ExpectMode)
-> Ord ExpectMode
ExpectMode -> ExpectMode -> Bool
ExpectMode -> ExpectMode -> Ordering
ExpectMode -> ExpectMode -> ExpectMode
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ExpectMode -> ExpectMode -> ExpectMode
$cmin :: ExpectMode -> ExpectMode -> ExpectMode
max :: ExpectMode -> ExpectMode -> ExpectMode
$cmax :: ExpectMode -> ExpectMode -> ExpectMode
>= :: ExpectMode -> ExpectMode -> Bool
$c>= :: ExpectMode -> ExpectMode -> Bool
> :: ExpectMode -> ExpectMode -> Bool
$c> :: ExpectMode -> ExpectMode -> Bool
<= :: ExpectMode -> ExpectMode -> Bool
$c<= :: ExpectMode -> ExpectMode -> Bool
< :: ExpectMode -> ExpectMode -> Bool
$c< :: ExpectMode -> ExpectMode -> Bool
compare :: ExpectMode -> ExpectMode -> Ordering
$ccompare :: ExpectMode -> ExpectMode -> Ordering
$cp1Ord :: Eq ExpectMode
Ord)
composeRequestBytes :: Request -> ByteString -> Builder
composeRequestBytes :: Request -> ByteString -> Builder
composeRequestBytes q :: Request
q h' :: ByteString
h' =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[Builder
requestline,
Builder
hostLine,
Builder
headerFields,
Builder
crlf]
where
requestline :: Builder
requestline = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[Builder
method,
Builder
sp,
Builder
uri,
Builder
sp,
Builder
version,
Builder
crlf]
method :: Builder
method = case Request -> Method
qMethod Request
q of
GET -> String -> Builder
Builder.fromString "GET"
HEAD -> String -> Builder
Builder.fromString "HEAD"
POST -> String -> Builder
Builder.fromString "POST"
PUT -> String -> Builder
Builder.fromString "PUT"
DELETE -> String -> Builder
Builder.fromString "DELETE"
TRACE -> String -> Builder
Builder.fromString "TRACE"
OPTIONS -> String -> Builder
Builder.fromString "OPTIONS"
CONNECT -> String -> Builder
Builder.fromString "CONNECT"
PATCH -> String -> Builder
Builder.fromString "PATCH"
(Method x :: ByteString
x) -> ByteString -> Builder
Builder.fromByteString ByteString
x
uri :: Builder
uri = case Request -> ByteString
qPath Request
q of
"" -> Char -> Builder
Builder.fromChar '/'
path :: ByteString
path -> ByteString -> Builder
Builder.copyByteString ByteString
path
version :: Builder
version = String -> Builder
Builder.fromString "HTTP/1.1"
hostLine :: Builder
hostLine = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[String -> Builder
Builder.fromString "Host: ",
Builder
hostname,
Builder
crlf]
hostname :: Builder
hostname = case Request -> Maybe ByteString
qHost Request
q of
Just x' :: ByteString
x' -> ByteString -> Builder
Builder.copyByteString ByteString
x'
Nothing -> ByteString -> Builder
Builder.copyByteString ByteString
h'
headerFields :: Builder
headerFields = HashMap (CI ByteString) ByteString -> Builder
joinHeaders (HashMap (CI ByteString) ByteString -> Builder)
-> HashMap (CI ByteString) ByteString -> Builder
forall a b. (a -> b) -> a -> b
$ Headers -> HashMap (CI ByteString) ByteString
unWrap (Headers -> HashMap (CI ByteString) ByteString)
-> Headers -> HashMap (CI ByteString) ByteString
forall a b. (a -> b) -> a -> b
$ Request -> Headers
qHeaders Request
q
crlf :: Builder
crlf = String -> Builder
Builder.fromString "\r\n"
sp :: Builder
sp = Char -> Builder
Builder.fromChar ' '
type StatusCode = Int
data Response
= Response {
Response -> Int
pStatusCode :: !StatusCode,
Response -> ByteString
pStatusMsg :: !ByteString,
Response -> TransferEncoding
pTransferEncoding :: !TransferEncoding,
Response -> ContentEncoding
pContentEncoding :: !ContentEncoding,
Response -> Maybe Int64
pContentLength :: !(Maybe Int64),
:: !Headers
}
instance Show Response where
show :: Response -> String
show p :: Response
p = {-# SCC "Response.show" #-}
ByteString -> String
S.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ByteString -> ByteString
S.filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '\r') (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Builder -> ByteString
Builder.toByteString (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ Response -> Builder
composeResponseBytes Response
p
data TransferEncoding = None | Chunked
data ContentEncoding = Identity | Gzip | Deflate
deriving (Int -> ContentEncoding -> ShowS
[ContentEncoding] -> ShowS
ContentEncoding -> String
(Int -> ContentEncoding -> ShowS)
-> (ContentEncoding -> String)
-> ([ContentEncoding] -> ShowS)
-> Show ContentEncoding
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ContentEncoding] -> ShowS
$cshowList :: [ContentEncoding] -> ShowS
show :: ContentEncoding -> String
$cshow :: ContentEncoding -> String
showsPrec :: Int -> ContentEncoding -> ShowS
$cshowsPrec :: Int -> ContentEncoding -> ShowS
Show)
getStatusCode :: Response -> StatusCode
getStatusCode :: Response -> Int
getStatusCode = Response -> Int
pStatusCode
{-# INLINE getStatusCode #-}
getStatusMessage :: Response -> ByteString
getStatusMessage :: Response -> ByteString
getStatusMessage = Response -> ByteString
pStatusMsg
{-# INLINE getStatusMessage #-}
getHeader :: Response -> ByteString -> Maybe ByteString
p :: Response
p k :: ByteString
k =
Headers -> ByteString -> Maybe ByteString
lookupHeader Headers
h ByteString
k
where
h :: Headers
h = Response -> Headers
pHeaders Response
p
class HttpType τ where
:: τ -> Headers
instance HttpType Request where
getHeaders :: Request -> Headers
getHeaders q :: Request
q = Request -> Headers
qHeaders Request
q
instance HttpType Response where
getHeaders :: Response -> Headers
getHeaders p :: Response
p = Response -> Headers
pHeaders Response
p
composeResponseBytes :: Response -> Builder
composeResponseBytes :: Response -> Builder
composeResponseBytes p :: Response
p =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[Builder
statusline,
Builder
headerFields,
Builder
crlf]
where
statusline :: Builder
statusline = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat
[Builder
version,
Builder
sp,
Builder
code,
Builder
sp,
Builder
message,
Builder
crlf]
code :: Builder
code = Int -> Builder
forall a. Show a => a -> Builder
Builder.fromShow (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ Response -> Int
pStatusCode Response
p
message :: Builder
message = ByteString -> Builder
Builder.copyByteString (ByteString -> Builder) -> ByteString -> Builder
forall a b. (a -> b) -> a -> b
$ Response -> ByteString
pStatusMsg Response
p
version :: Builder
version = String -> Builder
Builder.fromString "HTTP/1.1"
headerFields :: Builder
headerFields = HashMap (CI ByteString) ByteString -> Builder
joinHeaders (HashMap (CI ByteString) ByteString -> Builder)
-> HashMap (CI ByteString) ByteString -> Builder
forall a b. (a -> b) -> a -> b
$ Headers -> HashMap (CI ByteString) ByteString
unWrap (Headers -> HashMap (CI ByteString) ByteString)
-> Headers -> HashMap (CI ByteString) ByteString
forall a b. (a -> b) -> a -> b
$ Response -> Headers
pHeaders Response
p
newtype = Wrap {
Headers -> HashMap (CI ByteString) ByteString
unWrap :: HashMap (CI ByteString) ByteString
} deriving (Headers -> Headers -> Bool
(Headers -> Headers -> Bool)
-> (Headers -> Headers -> Bool) -> Eq Headers
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Headers -> Headers -> Bool
$c/= :: Headers -> Headers -> Bool
== :: Headers -> Headers -> Bool
$c== :: Headers -> Headers -> Bool
Eq)
instance Show Headers where
show :: Headers -> String
show x :: Headers
x = ByteString -> String
S.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> ByteString -> ByteString
S.filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '\r') (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Builder -> ByteString
Builder.toByteString (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ HashMap (CI ByteString) ByteString -> Builder
joinHeaders (HashMap (CI ByteString) ByteString -> Builder)
-> HashMap (CI ByteString) ByteString -> Builder
forall a b. (a -> b) -> a -> b
$ Headers -> HashMap (CI ByteString) ByteString
unWrap Headers
x
joinHeaders :: HashMap (CI ByteString) ByteString -> Builder
m :: HashMap (CI ByteString) ByteString
m = (CI ByteString -> ByteString -> Builder -> Builder)
-> Builder -> HashMap (CI ByteString) ByteString -> Builder
forall k v a. (k -> v -> a -> a) -> a -> HashMap k v -> a
foldrWithKey CI ByteString -> ByteString -> Builder -> Builder
combine Builder
forall a. Monoid a => a
mempty HashMap (CI ByteString) ByteString
m
combine :: CI ByteString -> ByteString -> Builder -> Builder
combine :: CI ByteString -> ByteString -> Builder -> Builder
combine k :: CI ByteString
k v :: ByteString
v acc :: Builder
acc =
[Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat [Builder
acc, Builder
key, String -> Builder
Builder.fromString ": ", Builder
value, Builder
crlf]
where
key :: Builder
key = ByteString -> Builder
Builder.copyByteString (ByteString -> Builder) -> ByteString -> Builder
forall a b. (a -> b) -> a -> b
$ CI ByteString -> ByteString
forall s. CI s -> s
original CI ByteString
k
value :: Builder
value = ByteString -> Builder
Builder.fromByteString ByteString
v
{-# INLINE combine #-}
emptyHeaders :: Headers
=
HashMap (CI ByteString) ByteString -> Headers
Wrap HashMap (CI ByteString) ByteString
forall k v. HashMap k v
empty
updateHeader :: Headers -> ByteString -> ByteString -> Headers
x :: Headers
x k :: ByteString
k v :: ByteString
v =
HashMap (CI ByteString) ByteString -> Headers
Wrap HashMap (CI ByteString) ByteString
result
where
!result :: HashMap (CI ByteString) ByteString
result = CI ByteString
-> ByteString
-> HashMap (CI ByteString) ByteString
-> HashMap (CI ByteString) ByteString
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
insert (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
mk ByteString
k) ByteString
v HashMap (CI ByteString) ByteString
m
!m :: HashMap (CI ByteString) ByteString
m = Headers -> HashMap (CI ByteString) ByteString
unWrap Headers
x
removeHeader :: Headers -> ByteString -> Headers
x :: Headers
x k :: ByteString
k =
HashMap (CI ByteString) ByteString -> Headers
Wrap HashMap (CI ByteString) ByteString
result
where
!result :: HashMap (CI ByteString) ByteString
result = CI ByteString
-> HashMap (CI ByteString) ByteString
-> HashMap (CI ByteString) ByteString
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
delete (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
mk ByteString
k) HashMap (CI ByteString) ByteString
m
!m :: HashMap (CI ByteString) ByteString
m = Headers -> HashMap (CI ByteString) ByteString
unWrap Headers
x
buildHeaders :: [(ByteString, ByteString)] -> Headers
hs :: [(ByteString, ByteString)]
hs =
HashMap (CI ByteString) ByteString -> Headers
Wrap HashMap (CI ByteString) ByteString
result
where
result :: HashMap (CI ByteString) ByteString
result = (HashMap (CI ByteString) ByteString
-> (ByteString, ByteString) -> HashMap (CI ByteString) ByteString)
-> HashMap (CI ByteString) ByteString
-> [(ByteString, ByteString)]
-> HashMap (CI ByteString) ByteString
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' HashMap (CI ByteString) ByteString
-> (ByteString, ByteString) -> HashMap (CI ByteString) ByteString
addHeader HashMap (CI ByteString) ByteString
forall k v. HashMap k v
empty [(ByteString, ByteString)]
hs
addHeader
:: HashMap (CI ByteString) ByteString
-> (ByteString,ByteString)
-> HashMap (CI ByteString) ByteString
m :: HashMap (CI ByteString) ByteString
m (k :: ByteString
k,v :: ByteString
v) =
(ByteString -> ByteString -> ByteString)
-> CI ByteString
-> ByteString
-> HashMap (CI ByteString) ByteString
-> HashMap (CI ByteString) ByteString
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> k -> v -> HashMap k v -> HashMap k v
insertWith ByteString -> ByteString -> ByteString
f (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
mk ByteString
k) ByteString
v HashMap (CI ByteString) ByteString
m
where
f :: ByteString -> ByteString -> ByteString
f new :: ByteString
new old :: ByteString
old = [ByteString] -> ByteString
S.concat [ByteString
old, ",", ByteString
new]
lookupHeader :: Headers -> ByteString -> Maybe ByteString
x :: Headers
x k :: ByteString
k =
CI ByteString
-> HashMap (CI ByteString) ByteString -> Maybe ByteString
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
lookup (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
mk ByteString
k) HashMap (CI ByteString) ByteString
m
where
!m :: HashMap (CI ByteString) ByteString
m = Headers -> HashMap (CI ByteString) ByteString
unWrap Headers
x
retrieveHeaders :: Headers -> [(ByteString, ByteString)]
x :: Headers
x =
((CI ByteString, ByteString) -> (ByteString, ByteString))
-> [(CI ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map (CI ByteString, ByteString) -> (ByteString, ByteString)
down ([(CI ByteString, ByteString)] -> [(ByteString, ByteString)])
-> [(CI ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a b. (a -> b) -> a -> b
$ HashMap (CI ByteString) ByteString -> [(CI ByteString, ByteString)]
forall k v. HashMap k v -> [(k, v)]
toList HashMap (CI ByteString) ByteString
m
where
!m :: HashMap (CI ByteString) ByteString
m = Headers -> HashMap (CI ByteString) ByteString
unWrap Headers
x
down :: (CI ByteString, ByteString) -> (ByteString, ByteString)
down :: (CI ByteString, ByteString) -> (ByteString, ByteString)
down (k :: CI ByteString
k, v :: ByteString
v) =
(CI ByteString -> ByteString
forall s. CI s -> s
original CI ByteString
k, ByteString
v)
data HttpParseException = HttpParseException String
deriving (Typeable, Int -> HttpParseException -> ShowS
[HttpParseException] -> ShowS
HttpParseException -> String
(Int -> HttpParseException -> ShowS)
-> (HttpParseException -> String)
-> ([HttpParseException] -> ShowS)
-> Show HttpParseException
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HttpParseException] -> ShowS
$cshowList :: [HttpParseException] -> ShowS
show :: HttpParseException -> String
$cshow :: HttpParseException -> String
showsPrec :: Int -> HttpParseException -> ShowS
$cshowsPrec :: Int -> HttpParseException -> ShowS
Show)
instance Exception HttpParseException