{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
module Network.HQ.Client (
run,
H3.ClientConfig (..),
H3.Config (..),
H3.allocSimpleConfig,
H3.freeSimpleConfig,
Scheme,
Authority,
Client,
Request,
requestNoBody,
Response,
getResponseBodyChunk,
) where
import qualified Control.Exception as E
import qualified Data.ByteString as BS
import Data.IORef
import Network.HPACK
import Network.HTTP.Semantics
import Network.HTTP.Semantics.Client
import Network.HTTP.Semantics.Client.Internal
import Network.QUIC (Connection)
import qualified Network.QUIC as QUIC
import Network.QUIC.Internal (possibleMyStreams)
import Imports
import qualified Network.HTTP3.Client as H3
import Network.HTTP3.Recv (newSource, readSource')
run :: Connection -> H3.ClientConfig -> H3.Config -> Client a -> IO a
run :: forall a. Connection -> ClientConfig -> Config -> Client a -> IO a
run Connection
conn ClientConfig
_ Config
_ Client a
client = Client a
client (Connection -> Request -> (Response -> IO r) -> IO r
forall a. Connection -> Request -> (Response -> IO a) -> IO a
sendRequest Connection
conn) Aux
aux
where
aux :: Aux
aux =
Aux
{ auxPossibleClientStreams :: IO Int
auxPossibleClientStreams = Connection -> IO Int
possibleMyStreams Connection
conn
}
sendRequest :: Connection -> Request -> (Response -> IO a) -> IO a
sendRequest :: forall a. Connection -> Request -> (Response -> IO a) -> IO a
sendRequest Connection
conn (Request OutObj
outobj) Response -> IO a
processResponse = IO Stream -> (Stream -> IO ()) -> (Stream -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
E.bracket IO Stream
open Stream -> IO ()
close ((Stream -> IO a) -> IO a) -> (Stream -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Stream
strm -> do
let hdr :: [Header]
hdr = OutObj -> [Header]
outObjHeaders OutObj
outobj
path :: ByteString
path = Maybe ByteString -> ByteString
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe ByteString -> ByteString) -> Maybe ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ HeaderName -> [Header] -> Maybe ByteString
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup HeaderName
":path" [Header]
hdr
requestLine :: ByteString
requestLine = [ByteString] -> ByteString
BS.concat [ByteString
"GET ", ByteString
path, ByteString
"\r\n"]
Stream -> ByteString -> IO ()
QUIC.sendStream Stream
strm ByteString
requestLine
Stream -> IO ()
QUIC.shutdownStream Stream
strm
Source
src <- Stream -> IO Source
newSource Stream
strm
IORef (Maybe TokenHeaderTable)
refH <- Maybe TokenHeaderTable -> IO (IORef (Maybe TokenHeaderTable))
forall a. a -> IO (IORef a)
newIORef Maybe TokenHeaderTable
forall a. Maybe a
Nothing
TokenHeaderTable
vt <- [Header] -> IO TokenHeaderTable
toTokenHeaderTable []
let readB :: IO (ByteString, Bool)
readB = Source -> IO (ByteString, Bool)
readSource' Source
src
rsp :: Response
rsp = InpObj -> Response
Response (InpObj -> Response) -> InpObj -> Response
forall a b. (a -> b) -> a -> b
$ TokenHeaderTable
-> Maybe Int
-> IO (ByteString, Bool)
-> IORef (Maybe TokenHeaderTable)
-> InpObj
InpObj TokenHeaderTable
vt Maybe Int
forall a. Maybe a
Nothing IO (ByteString, Bool)
readB IORef (Maybe TokenHeaderTable)
refH
Response -> IO a
processResponse Response
rsp
where
open :: IO Stream
open = Connection -> IO Stream
QUIC.stream Connection
conn
close :: Stream -> IO ()
close = Stream -> IO ()
QUIC.closeStream