module Network.HTTP.HandleStream
( simpleHTTP
, simpleHTTP_
, sendHTTP
, sendHTTP_notify
, receiveHTTP
, respondHTTP
, simpleHTTP_debug
) where
import Network.BufferType
import Network.Stream ( fmapE, Result )
import Network.StreamDebugger ( debugByteStream )
import Network.TCP (HStream(..), HandleStream )
import Network.HTTP.Base
import Network.HTTP.Headers
import Network.HTTP.Utils ( trim, readsOne )
import Data.Char (toLower)
import Data.Maybe (fromMaybe)
import Control.Exception (onException)
import Control.Monad (when)
simpleHTTP :: HStream ty => Request ty -> IO (Result (Response ty))
simpleHTTP :: Request ty -> IO (Result (Response ty))
simpleHTTP Request ty
r = do
URIAuthority
auth <- Request ty -> IO URIAuthority
forall (m :: * -> *) ty.
MonadFail m =>
Request ty -> m URIAuthority
getAuth Request ty
r
URI -> IO ()
forall (m :: * -> *). MonadFail m => URI -> m ()
failHTTPS (Request ty -> URI
forall a. Request a -> URI
rqURI Request ty
r)
HandleStream ty
c <- String -> Int -> IO (HandleStream ty)
forall bufType.
HStream bufType =>
String -> Int -> IO (HandleStream bufType)
openStream (URIAuthority -> String
host URIAuthority
auth) (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
80 (URIAuthority -> Maybe Int
port URIAuthority
auth))
HandleStream ty -> Request ty -> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty -> Request ty -> IO (Result (Response ty))
simpleHTTP_ HandleStream ty
c Request ty
r
simpleHTTP_debug :: HStream ty => FilePath -> Request ty -> IO (Result (Response ty))
simpleHTTP_debug :: String -> Request ty -> IO (Result (Response ty))
simpleHTTP_debug String
httpLogFile Request ty
r = do
URIAuthority
auth <- Request ty -> IO URIAuthority
forall (m :: * -> *) ty.
MonadFail m =>
Request ty -> m URIAuthority
getAuth Request ty
r
URI -> IO ()
forall (m :: * -> *). MonadFail m => URI -> m ()
failHTTPS (Request ty -> URI
forall a. Request a -> URI
rqURI Request ty
r)
HandleStream ty
c0 <- String -> Int -> IO (HandleStream ty)
forall bufType.
HStream bufType =>
String -> Int -> IO (HandleStream bufType)
openStream (URIAuthority -> String
host URIAuthority
auth) (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
80 (URIAuthority -> Maybe Int
port URIAuthority
auth))
HandleStream ty
c <- String -> HandleStream ty -> IO (HandleStream ty)
forall ty.
HStream ty =>
String -> HandleStream ty -> IO (HandleStream ty)
debugByteStream String
httpLogFile HandleStream ty
c0
HandleStream ty -> Request ty -> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty -> Request ty -> IO (Result (Response ty))
simpleHTTP_ HandleStream ty
c Request ty
r
simpleHTTP_ :: HStream ty => HandleStream ty -> Request ty -> IO (Result (Response ty))
simpleHTTP_ :: HandleStream ty -> Request ty -> IO (Result (Response ty))
simpleHTTP_ HandleStream ty
s Request ty
r = HandleStream ty -> Request ty -> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty -> Request ty -> IO (Result (Response ty))
sendHTTP HandleStream ty
s Request ty
r
sendHTTP :: HStream ty => HandleStream ty -> Request ty -> IO (Result (Response ty))
sendHTTP :: HandleStream ty -> Request ty -> IO (Result (Response ty))
sendHTTP HandleStream ty
conn Request ty
rq = HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
sendHTTP_notify HandleStream ty
conn Request ty
rq (() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
sendHTTP_notify :: HStream ty
=> HandleStream ty
-> Request ty
-> IO ()
-> IO (Result (Response ty))
sendHTTP_notify :: HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
sendHTTP_notify HandleStream ty
conn Request ty
rq IO ()
onSendComplete = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
providedClose (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ (HandleStream ty -> Bool -> IO ()
forall bufType.
HStream bufType =>
HandleStream bufType -> Bool -> IO ()
closeOnEnd HandleStream ty
conn Bool
True)
IO (Result (Response ty)) -> IO () -> IO (Result (Response ty))
forall a b. IO a -> IO b -> IO a
onException (HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
sendMain HandleStream ty
conn Request ty
rq IO ()
onSendComplete)
(HandleStream ty -> IO ()
forall bufType. HStream bufType => HandleStream bufType -> IO ()
close HandleStream ty
conn)
where
providedClose :: Bool
providedClose = [Header] -> Bool
findConnClose (Request ty -> [Header]
forall a. Request a -> [Header]
rqHeaders Request ty
rq)
sendMain :: HStream ty
=> HandleStream ty
-> Request ty
-> (IO ())
-> IO (Result (Response ty))
sendMain :: HandleStream ty -> Request ty -> IO () -> IO (Result (Response ty))
sendMain HandleStream ty
conn Request ty
rqst IO ()
onSendComplete = do
Result ()
_ <- HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn (BufferOp ty -> String -> ty
forall a. BufferOp a -> String -> a
buf_fromStr BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps (String -> ty) -> String -> ty
forall a b. (a -> b) -> a -> b
$ Request ty -> String
forall a. Show a => a -> String
show Request ty
rqst)
Result ()
_ <- HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn (Request ty -> ty
forall a. Request a -> a
rqBody Request ty
rqst)
IO ()
onSendComplete
Result ResponseData
rsp <- HandleStream ty -> IO (Result ResponseData)
forall ty.
HStream ty =>
HandleStream ty -> IO (Result ResponseData)
getResponseHead HandleStream ty
conn
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse HandleStream ty
conn Bool
True Bool
False Result ResponseData
rsp Request ty
rqst
switchResponse :: HStream ty
=> HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse :: HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse HandleStream ty
_ Bool
_ Bool
_ (Left ConnError
e) Request ty
_ = Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return (ConnError -> Result (Response ty)
forall a b. a -> Either a b
Left ConnError
e)
switchResponse HandleStream ty
conn Bool
allow_retry Bool
bdy_sent (Right (ResponseCode
cd,String
rn,[Header]
hdrs)) Request ty
rqst =
case RequestMethod -> ResponseCode -> ResponseNextStep
matchResponse (Request ty -> RequestMethod
forall a. Request a -> RequestMethod
rqMethod Request ty
rqst) ResponseCode
cd of
ResponseNextStep
Continue
| Bool -> Bool
not Bool
bdy_sent -> do
HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn (Request ty -> ty
forall a. Request a -> a
rqBody Request ty
rqst) IO (Result ())
-> (Result () -> IO (Result (Response ty)))
-> IO (Result (Response ty))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ConnError -> IO (Result (Response ty)))
-> (() -> IO (Result (Response ty)))
-> Result ()
-> IO (Result (Response ty))
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return (Result (Response ty) -> IO (Result (Response ty)))
-> (ConnError -> Result (Response ty))
-> ConnError
-> IO (Result (Response ty))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnError -> Result (Response ty)
forall a b. a -> Either a b
Left)
(\ ()
_ -> do
Result ResponseData
rsp <- HandleStream ty -> IO (Result ResponseData)
forall ty.
HStream ty =>
HandleStream ty -> IO (Result ResponseData)
getResponseHead HandleStream ty
conn
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse HandleStream ty
conn Bool
allow_retry Bool
True Result ResponseData
rsp Request ty
rqst)
| Bool
otherwise -> do
Result ResponseData
rsp <- HandleStream ty -> IO (Result ResponseData)
forall ty.
HStream ty =>
HandleStream ty -> IO (Result ResponseData)
getResponseHead HandleStream ty
conn
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse HandleStream ty
conn Bool
allow_retry Bool
bdy_sent Result ResponseData
rsp Request ty
rqst
ResponseNextStep
Retry -> do
Result ()
_ <- HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn ((BufferOp ty -> ty -> ty -> ty
forall a. BufferOp a -> a -> a -> a
buf_append BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps)
(BufferOp ty -> String -> ty
forall a. BufferOp a -> String -> a
buf_fromStr BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps (Request ty -> String
forall a. Show a => a -> String
show Request ty
rqst))
(Request ty -> ty
forall a. Request a -> a
rqBody Request ty
rqst))
Result ResponseData
rsp <- HandleStream ty -> IO (Result ResponseData)
forall ty.
HStream ty =>
HandleStream ty -> IO (Result ResponseData)
getResponseHead HandleStream ty
conn
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
forall ty.
HStream ty =>
HandleStream ty
-> Bool
-> Bool
-> Result ResponseData
-> Request ty
-> IO (Result (Response ty))
switchResponse HandleStream ty
conn Bool
False Bool
bdy_sent Result ResponseData
rsp Request ty
rqst
ResponseNextStep
Done -> do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([Header] -> Bool
findConnClose [Header]
hdrs)
(HandleStream ty -> Bool -> IO ()
forall bufType.
HStream bufType =>
HandleStream bufType -> Bool -> IO ()
closeOnEnd HandleStream ty
conn Bool
True)
Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return (Response ty -> Result (Response ty)
forall a b. b -> Either a b
Right (Response ty -> Result (Response ty))
-> Response ty -> Result (Response ty)
forall a b. (a -> b) -> a -> b
$ ResponseCode -> String -> [Header] -> ty -> Response ty
forall a. ResponseCode -> String -> [Header] -> a -> Response a
Response ResponseCode
cd String
rn [Header]
hdrs (BufferOp ty -> ty
forall a. BufferOp a -> a
buf_empty BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps))
DieHorribly String
str -> do
HandleStream ty -> IO ()
forall bufType. HStream bufType => HandleStream bufType -> IO ()
close HandleStream ty
conn
Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> String -> Result (Response ty)
forall a. String -> String -> Result a
responseParseError String
"Invalid response:" String
str)
ResponseNextStep
ExpectEntity -> do
Result (Response ty)
r <- (([Header], ty) -> Result (Response ty))
-> IO (Result ([Header], ty)) -> IO (Result (Response ty))
forall a b. (a -> Result b) -> IO (Result a) -> IO (Result b)
fmapE (\ ([Header]
ftrs,ty
bdy) -> Response ty -> Result (Response ty)
forall a b. b -> Either a b
Right (ResponseCode -> String -> [Header] -> ty -> Response ty
forall a. ResponseCode -> String -> [Header] -> a -> Response a
Response ResponseCode
cd String
rn ([Header]
hdrs[Header] -> [Header] -> [Header]
forall a. [a] -> [a] -> [a]
++[Header]
ftrs) ty
bdy)) (IO (Result ([Header], ty)) -> IO (Result (Response ty)))
-> IO (Result ([Header], ty)) -> IO (Result (Response ty))
forall a b. (a -> b) -> a -> b
$
IO (Result ([Header], ty))
-> (String -> IO (Result ([Header], ty)))
-> Maybe String
-> IO (Result ([Header], ty))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (IO (Result ([Header], ty))
-> (String -> IO (Result ([Header], ty)))
-> Maybe String
-> IO (Result ([Header], ty))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (BufferOp ty -> IO (Result ty) -> [ty] -> IO (Result ([Header], ty))
forall a.
BufferOp a -> IO (Result a) -> [a] -> IO (Result ([Header], a))
hopefulTransfer BufferOp ty
bo (HandleStream ty -> IO (Result ty)
forall bufType.
HStream bufType =>
HandleStream bufType -> IO (Result bufType)
readLine HandleStream ty
conn) [])
(\ String
x ->
(Int -> IO (Result ([Header], ty)))
-> IO (Result ([Header], ty))
-> String
-> IO (Result ([Header], ty))
forall a b. Read a => (a -> b) -> b -> String -> b
readsOne ((Int -> IO (Result ty)) -> Int -> IO (Result ([Header], ty))
forall a.
(Int -> IO (Result a)) -> Int -> IO (Result ([Header], a))
linearTransfer (HandleStream ty -> Int -> IO (Result ty)
forall bufType.
HStream bufType =>
HandleStream bufType -> Int -> IO (Result bufType)
readBlock HandleStream ty
conn))
(Result ([Header], ty) -> IO (Result ([Header], ty))
forall (m :: * -> *) a. Monad m => a -> m a
return(Result ([Header], ty) -> IO (Result ([Header], ty)))
-> Result ([Header], ty) -> IO (Result ([Header], ty))
forall a b. (a -> b) -> a -> b
$String -> String -> Result ([Header], ty)
forall a. String -> String -> Result a
responseParseError String
"unrecognized content-length value" String
x)
String
x)
Maybe String
cl)
(IO (Result ([Header], ty))
-> IO (Result ([Header], ty))
-> String
-> IO (Result ([Header], ty))
forall a. a -> a -> String -> a
ifChunked (BufferOp ty
-> IO (Result ty)
-> (Int -> IO (Result ty))
-> IO (Result ([Header], ty))
forall a.
BufferOp a
-> IO (Result a)
-> (Int -> IO (Result a))
-> IO (Result ([Header], a))
chunkedTransfer BufferOp ty
bo (HandleStream ty -> IO (Result ty)
forall bufType.
HStream bufType =>
HandleStream bufType -> IO (Result bufType)
readLine HandleStream ty
conn) (HandleStream ty -> Int -> IO (Result ty)
forall bufType.
HStream bufType =>
HandleStream bufType -> Int -> IO (Result bufType)
readBlock HandleStream ty
conn))
(String -> IO (Result ([Header], ty))
forall a. String -> IO (Result ([Header], a))
uglyDeathTransfer String
"sendHTTP"))
Maybe String
tc
case Result (Response ty)
r of
Left{} -> do
HandleStream ty -> IO ()
forall bufType. HStream bufType => HandleStream bufType -> IO ()
close HandleStream ty
conn
Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return Result (Response ty)
r
Right (Response ResponseCode
_ String
_ [Header]
hs ty
_) -> do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([Header] -> Bool
findConnClose [Header]
hs)
(HandleStream ty -> Bool -> IO ()
forall bufType.
HStream bufType =>
HandleStream bufType -> Bool -> IO ()
closeOnEnd HandleStream ty
conn Bool
True)
Result (Response ty) -> IO (Result (Response ty))
forall (m :: * -> *) a. Monad m => a -> m a
return Result (Response ty)
r
where
tc :: Maybe String
tc = HeaderName -> [Header] -> Maybe String
lookupHeader HeaderName
HdrTransferEncoding [Header]
hdrs
cl :: Maybe String
cl = HeaderName -> [Header] -> Maybe String
lookupHeader HeaderName
HdrContentLength [Header]
hdrs
bo :: BufferOp ty
bo = BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps
getResponseHead :: HStream ty => HandleStream ty -> IO (Result ResponseData)
getResponseHead :: HandleStream ty -> IO (Result ResponseData)
getResponseHead HandleStream ty
conn =
([ty] -> Result ResponseData)
-> IO (Result [ty]) -> IO (Result ResponseData)
forall a b. (a -> Result b) -> IO (Result a) -> IO (Result b)
fmapE (\[ty]
es -> [String] -> Result ResponseData
parseResponseHead ((ty -> String) -> [ty] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (BufferOp ty -> ty -> String
forall a. BufferOp a -> a -> String
buf_toStr BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps) [ty]
es))
(BufferOp ty -> IO (Result ty) -> IO (Result [ty])
forall a. BufferOp a -> IO (Result a) -> IO (Result [a])
readTillEmpty1 BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps (HandleStream ty -> IO (Result ty)
forall bufType.
HStream bufType =>
HandleStream bufType -> IO (Result bufType)
readLine HandleStream ty
conn))
receiveHTTP :: HStream bufTy => HandleStream bufTy -> IO (Result (Request bufTy))
receiveHTTP :: HandleStream bufTy -> IO (Result (Request bufTy))
receiveHTTP HandleStream bufTy
conn = IO (Result RequestData)
getRequestHead IO (Result RequestData)
-> (Result RequestData -> IO (Result (Request bufTy)))
-> IO (Result (Request bufTy))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ConnError -> IO (Result (Request bufTy)))
-> (RequestData -> IO (Result (Request bufTy)))
-> Result RequestData
-> IO (Result (Request bufTy))
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Result (Request bufTy) -> IO (Result (Request bufTy))
forall (m :: * -> *) a. Monad m => a -> m a
return (Result (Request bufTy) -> IO (Result (Request bufTy)))
-> (ConnError -> Result (Request bufTy))
-> ConnError
-> IO (Result (Request bufTy))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ConnError -> Result (Request bufTy)
forall a b. a -> Either a b
Left) RequestData -> IO (Result (Request bufTy))
processRequest
where
getRequestHead :: IO (Result RequestData)
getRequestHead :: IO (Result RequestData)
getRequestHead = do
([bufTy] -> Result RequestData)
-> IO (Result [bufTy]) -> IO (Result RequestData)
forall a b. (a -> Result b) -> IO (Result a) -> IO (Result b)
fmapE (\[bufTy]
es -> [String] -> Result RequestData
parseRequestHead ((bufTy -> String) -> [bufTy] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (BufferOp bufTy -> bufTy -> String
forall a. BufferOp a -> a -> String
buf_toStr BufferOp bufTy
forall bufType. BufferType bufType => BufferOp bufType
bufferOps) [bufTy]
es))
(BufferOp bufTy -> IO (Result bufTy) -> IO (Result [bufTy])
forall a. BufferOp a -> IO (Result a) -> IO (Result [a])
readTillEmpty1 BufferOp bufTy
forall bufType. BufferType bufType => BufferOp bufType
bufferOps (HandleStream bufTy -> IO (Result bufTy)
forall bufType.
HStream bufType =>
HandleStream bufType -> IO (Result bufType)
readLine HandleStream bufTy
conn))
processRequest :: RequestData -> IO (Result (Request bufTy))
processRequest (RequestMethod
rm,URI
uri,[Header]
hdrs) =
(([Header], bufTy) -> Result (Request bufTy))
-> IO (Result ([Header], bufTy)) -> IO (Result (Request bufTy))
forall a b. (a -> Result b) -> IO (Result a) -> IO (Result b)
fmapE (\ ([Header]
ftrs,bufTy
bdy) -> Request bufTy -> Result (Request bufTy)
forall a b. b -> Either a b
Right (URI -> RequestMethod -> [Header] -> bufTy -> Request bufTy
forall a. URI -> RequestMethod -> [Header] -> a -> Request a
Request URI
uri RequestMethod
rm ([Header]
hdrs[Header] -> [Header] -> [Header]
forall a. [a] -> [a] -> [a]
++[Header]
ftrs) bufTy
bdy)) (IO (Result ([Header], bufTy)) -> IO (Result (Request bufTy)))
-> IO (Result ([Header], bufTy)) -> IO (Result (Request bufTy))
forall a b. (a -> b) -> a -> b
$
IO (Result ([Header], bufTy))
-> (String -> IO (Result ([Header], bufTy)))
-> Maybe String
-> IO (Result ([Header], bufTy))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
(IO (Result ([Header], bufTy))
-> (String -> IO (Result ([Header], bufTy)))
-> Maybe String
-> IO (Result ([Header], bufTy))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Result ([Header], bufTy) -> IO (Result ([Header], bufTy))
forall (m :: * -> *) a. Monad m => a -> m a
return (([Header], bufTy) -> Result ([Header], bufTy)
forall a b. b -> Either a b
Right ([], BufferOp bufTy -> bufTy
forall a. BufferOp a -> a
buf_empty BufferOp bufTy
bo)))
(\ String
x -> (Int -> IO (Result ([Header], bufTy)))
-> IO (Result ([Header], bufTy))
-> String
-> IO (Result ([Header], bufTy))
forall a b. Read a => (a -> b) -> b -> String -> b
readsOne ((Int -> IO (Result bufTy)) -> Int -> IO (Result ([Header], bufTy))
forall a.
(Int -> IO (Result a)) -> Int -> IO (Result ([Header], a))
linearTransfer (HandleStream bufTy -> Int -> IO (Result bufTy)
forall bufType.
HStream bufType =>
HandleStream bufType -> Int -> IO (Result bufType)
readBlock HandleStream bufTy
conn))
(Result ([Header], bufTy) -> IO (Result ([Header], bufTy))
forall (m :: * -> *) a. Monad m => a -> m a
return(Result ([Header], bufTy) -> IO (Result ([Header], bufTy)))
-> Result ([Header], bufTy) -> IO (Result ([Header], bufTy))
forall a b. (a -> b) -> a -> b
$String -> String -> Result ([Header], bufTy)
forall a. String -> String -> Result a
responseParseError String
"unrecognized Content-Length value" String
x)
String
x)
Maybe String
cl)
(IO (Result ([Header], bufTy))
-> IO (Result ([Header], bufTy))
-> String
-> IO (Result ([Header], bufTy))
forall a. a -> a -> String -> a
ifChunked (BufferOp bufTy
-> IO (Result bufTy)
-> (Int -> IO (Result bufTy))
-> IO (Result ([Header], bufTy))
forall a.
BufferOp a
-> IO (Result a)
-> (Int -> IO (Result a))
-> IO (Result ([Header], a))
chunkedTransfer BufferOp bufTy
bo (HandleStream bufTy -> IO (Result bufTy)
forall bufType.
HStream bufType =>
HandleStream bufType -> IO (Result bufType)
readLine HandleStream bufTy
conn) (HandleStream bufTy -> Int -> IO (Result bufTy)
forall bufType.
HStream bufType =>
HandleStream bufType -> Int -> IO (Result bufType)
readBlock HandleStream bufTy
conn))
(String -> IO (Result ([Header], bufTy))
forall a. String -> IO (Result ([Header], a))
uglyDeathTransfer String
"receiveHTTP"))
Maybe String
tc
where
tc :: Maybe String
tc = HeaderName -> [Header] -> Maybe String
lookupHeader HeaderName
HdrTransferEncoding [Header]
hdrs
cl :: Maybe String
cl = HeaderName -> [Header] -> Maybe String
lookupHeader HeaderName
HdrContentLength [Header]
hdrs
bo :: BufferOp bufTy
bo = BufferOp bufTy
forall bufType. BufferType bufType => BufferOp bufType
bufferOps
respondHTTP :: HStream ty => HandleStream ty -> Response ty -> IO ()
respondHTTP :: HandleStream ty -> Response ty -> IO ()
respondHTTP HandleStream ty
conn Response ty
rsp = do
Result ()
_ <- HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn (BufferOp ty -> String -> ty
forall a. BufferOp a -> String -> a
buf_fromStr BufferOp ty
forall bufType. BufferType bufType => BufferOp bufType
bufferOps (String -> ty) -> String -> ty
forall a b. (a -> b) -> a -> b
$ Response ty -> String
forall a. Show a => a -> String
show Response ty
rsp)
Result ()
_ <- HandleStream ty -> ty -> IO (Result ())
forall bufType.
HStream bufType =>
HandleStream bufType -> bufType -> IO (Result ())
writeBlock HandleStream ty
conn (Response ty -> ty
forall a. Response a -> a
rspBody Response ty
rsp)
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
headerName :: String -> String
String
x = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> String
trim String
x)
ifChunked :: a -> a -> String -> a
ifChunked :: a -> a -> String -> a
ifChunked a
a a
b String
s =
case String -> String
headerName String
s of
String
"chunked" -> a
a
String
_ -> a
b