module Network.IHttp.Response
(
response,
responseLine,
enumResponse,
enumResponseLine
)
where
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC
import Data.ByteString (ByteString)
import Data.Enumerator as E
import Data.Enumerator.List as EL
import Network.IHttp.Header
import Network.IHttp.Parsers
import Network.IHttp.Tools
import Network.IHttp.Types
enumResponse :: forall b m. Monad m => Response -> Enumerator ByteString m b
enumResponse resp =
E.concatEnums [ enumResponseLine (responseVersion resp)
(responseCode resp)
(responseMessage resp),
enumHeaders (responseHeaders resp),
emptyLine ]
where
emptyLine :: Enumerator ByteString m b
emptyLine (Continue k) = k (Chunks ["\r\n"])
emptyLine step = returnI step
enumResponseLine ::
forall b m. Monad m =>
HttpVersion -> Int -> ByteString -> Enumerator ByteString m b
enumResponseLine version code msg = enum
where
enum :: Enumerator ByteString m b
enum (Continue k) = k (Chunks respChunks)
enum step = returnI step
respChunks :: [ByteString]
respChunks =
let space = B.singleton 32 in
[ showVersion version, space, intStr code, space, msg, "\r\n" ]
intStr :: Int -> ByteString
intStr n | n < 0 = BC.cons '-' (intStr (negate n))
intStr 0 = BC.singleton '0'
intStr n = intStr' B.empty n
where
intStr' :: ByteString -> Int -> ByteString
intStr' str 0 = str
intStr' str n =
let (q,r) = quotRem n 10 in
intStr' (B.cons (fromIntegral r + 48) str) q
response :: Monad m => Int -> Int -> Iteratee ByteString m Response
response maxHeadLine maxHeaders = do
req <- responseLine
headers <- httpHeaders maxHeadLine maxHeaders
return req { responseHeaders = headers }
responseLine :: Monad m => Iteratee ByteString m Response
responseLine =
EL.head
>>= maybe (throwError $ InvalidResponseError "Premature end of stream") return
>>= parseIter responseLineP InvalidResponseError