-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A native HTTP2 client library. -- -- Please read the README.md at the homepage. @package http2-client @version 0.3.0.0 module Network.HTTP2.Client.RawConnection data RawHttp2Connection RawHttp2Connection :: (ByteString -> IO ()) -> (Int -> IO ByteString) -> IO () -> RawHttp2Connection -- | Function to send raw data to the server. [_sendRaw] :: RawHttp2Connection -> ByteString -> IO () -- | Function to block reading a datachunk of a given size from the server. [_nextRaw] :: RawHttp2Connection -> Int -> IO ByteString [_close] :: RawHttp2Connection -> IO () -- | Initiates a RawHttp2Connection with a server. -- -- The current code does not handle closing the connexion, yikes. newRawHttp2Connection :: HostName -> PortNumber -> ClientParams -> IO RawHttp2Connection module Network.HTTP2.Client.FrameConnection data Http2FrameConnection Http2FrameConnection :: (StreamId -> Http2FrameClientStream) -> Http2ServerStream -> IO () -> Http2FrameConnection -- | Starts a new client stream. [_makeFrameClientStream] :: Http2FrameConnection -> StreamId -> Http2FrameClientStream -- | Receives frames from a server. [_serverStream] :: Http2FrameConnection -> Http2ServerStream -- | Function that will close the network connection. [_closeConnection] :: Http2FrameConnection -> IO () -- | Creates a new Http2FrameConnection to a given host for a -- frame-to-frame communication. newHttp2FrameConnection :: HostName -> PortNumber -> ClientParams -> IO Http2FrameConnection data Http2ServerStream Http2ServerStream :: IO (FrameHeader, Either HTTP2Error FramePayload) -> Http2ServerStream [_nextHeaderAndFrame] :: Http2ServerStream -> IO (FrameHeader, Either HTTP2Error FramePayload) data Http2FrameClientStream Http2FrameClientStream :: ([(FrameFlags -> FrameFlags, FramePayload)] -> IO ()) -> StreamId -> Http2FrameClientStream -- | Sends a frame to the server. The first argument is a FrameFlags -- modifier (e.g., to sed the end-of-stream flag). [_sendFrames] :: Http2FrameClientStream -> [(FrameFlags -> FrameFlags, FramePayload)] -> IO () [_getStreamId] :: Http2FrameClientStream -> StreamId -- | Creates a client stream. makeFrameClientStream :: Http2FrameConnection -> StreamId -> Http2FrameClientStream -- | Sends a frame to the server. sendOne :: Http2FrameClientStream -> (FrameFlags -> FrameFlags) -> FramePayload -> IO () -- | Sends multiple back-to-back frames to the server. sendBackToBack :: Http2FrameClientStream -> [(FrameFlags -> FrameFlags, FramePayload)] -> IO () -- | Waits for the next frame from the server. next :: Http2FrameConnection -> IO (FrameHeader, Either HTTP2Error FramePayload) -- | Closes the Http2FrameConnection abruptly. closeConnection :: Http2FrameConnection -> IO () -- | This module defines a set of low-level primitives for starting an -- HTTP2 session and interacting with a server. -- -- For higher-level primitives, please refer to -- Network.HTTP2.Client.Helpers . module Network.HTTP2.Client -- | Starts a new Http2Client with a remote Host/Port. TLS ClientParams are -- mandatory because we only support TLS-protected streams for now. newHttp2Client :: HostName -> PortNumber -> Int -> Int -> ClientParams -> SettingsList -> IO Http2Client -- | Starts a new stream (i.e., one HTTP request + server-pushes). -- -- You will typically call the returned StreamStarter immediately -- to define what you want to do with the Http2Stream. -- --
--   _ (withHttp2Stream myClient $ stream - StreamDefinition _ _)
--   
-- -- Please refer to StreamStarter and StreamDefinition for -- more. withHttp2Stream :: Http2Client -> StreamStarter a -- | Sends the HTTP2+HTTP headers of your chosing. -- -- You must add HTTP2 pseudo-headers first, followed by your typical HTTP -- headers. This function makes no verification of this -- ordering/exhaustinevess. -- -- HTTP2 pseudo-headers replace the HTTP verb + parsed url as follows: -- ":method" such as GET, ":scheme" such as "https", ":path" such -- as "blogpost/1234?foo=bar", ":authority" such as "haskell.org" -- -- Note that we currently enforce the setEndHeader but this design -- choice may change in the future. Hence, we recommend you use -- setEndHeader as well. headers :: Http2Stream -> HeaderList -> FlagSetter -> IO StreamThread -- | Sends data, chunked according to the server's preferred chunk size. -- -- This function does not respect HTTP2 flow-control and send chunks -- sequentially. Hence, you should first ensure that you have enough -- flow-control credit (with _withdrawCredit) or risk a connection -- failure. When you call _withdrawCredit keep in mind that HTTP2 has -- flow control at the stream and at the connection level. If you use -- `http2-client` in a multithreaded conext, you should avoid starving -- the connection-level flow-control. -- -- If you want to send bytestrings that fit in RAM, you can use -- upload as a function that implements flow-control. -- -- This function does not send frames back-to-back, that is, other frames -- may get interleaved between two chunks (for instance, to give priority -- to other streams, although no priority queue exists in `http2-client` -- so far). -- -- Please refer to _sendDataChunk and _withdrawCredit as -- well. sendData :: Http2Client -> Http2Stream -> FlagSetter -> ByteString -> IO () -- | Record holding functions one can call while in an HTTP2 client -- session. data Http2Client Http2Client :: (ByteString -> IO (IO (FrameHeader, FramePayload))) -> (SettingsList -> IO (IO (FrameHeader, FramePayload))) -> (ErrorCodeId -> ByteString -> IO ()) -> (forall a. StreamStarter a) -> IncomingFlowControl -> OutgoingFlowControl -> IO PayloadSplitter -> Http2Client -- | Send a PING, the payload size must be exactly eight bytes. Returns an -- IO to wait for a ping reply. No timeout is provided. Only the first -- call to this IO will return if a reply is received. Hence we recommend -- wrapping this IO in an Async (e.g., with race (threadDelay -- timeout).) [_ping] :: Http2Client -> ByteString -> IO (IO (FrameHeader, FramePayload)) -- | Sends a SETTINGS. Returns an IO to wait for a settings reply. No -- timeout is provided. Only the first call to this IO will return if a -- reply is received. Hence we recommend wrapping this IO in an Async -- (e.g., with race (threadDelay timeout).) [_settings] :: Http2Client -> SettingsList -> IO (IO (FrameHeader, FramePayload)) -- | Sends a GOAWAY. [_goaway] :: Http2Client -> ErrorCodeId -> ByteString -> IO () -- | Spawns new streams. See StreamStarter. [_startStream] :: Http2Client -> forall a. StreamStarter a -- | Simple getter for the IncomingFlowControl for the whole client -- connection. [_incomingFlowControl] :: Http2Client -> IncomingFlowControl -- | Simple getter for the OutgoingFlowControl for the whole client -- connection. [_outgoingFlowControl] :: Http2Client -> OutgoingFlowControl -- | Returns a function to split a payload. [_paylodSplitter] :: Http2Client -> IO PayloadSplitter -- | Handler upon receiving a PUSH_PROMISE from the server. -- -- The functions for Http2Stream are similar to those used in ''. -- But callers shall not use _headers to initialize the -- PUSH_PROMISE stream. Rather, callers should waitHeaders or -- _rst to reject the PUSH_PROMISE. -- -- The StreamId corresponds to the parent stream as PUSH_PROMISEs are -- tied to a client-initiated stream. Longer term we may move passing -- this handler to the _startStream instead of -- newHttp2Client (as it is for now). type PushPromiseHandler = StreamId -> Http2Stream -> HeaderList -> IncomingFlowControl -> OutgoingFlowControl -> IO () -- | Defines a client stream. -- -- Please red the doc for this record fields and then see -- StreamStarter. data StreamDefinition a StreamDefinition :: IO StreamThread -> (IncomingFlowControl -> OutgoingFlowControl -> IO a) -> StreamDefinition a -- | Function to initialize a new client stream. This function runs in a -- exclusive-access section of the code and may prevent other threads to -- initialize new streams. Hence, you should ensure this IO does not wait -- for long periods of time. [_initStream] :: StreamDefinition a -> IO StreamThread -- | Function to operate with the stream. IncomingFlowControl currently is -- credited on your behalf as soon as a DATA frame arrives (and before -- you handle it with _waitData). However we do not send -- WINDOW_UPDATE with _updateWindow. This design may change in the -- future to give more leeway to library users. [_handleStream] :: StreamDefinition a -> IncomingFlowControl -> OutgoingFlowControl -> IO a -- | Type alias for callback-based functions starting new streams. -- -- The callback a user must provide takes an Http2Stream and -- returns a StreamDefinition. This construction may seem wrong -- because a StreamDefinition contains an initialization and a -- handler functions. The explanation for this twistedness is as follows: -- in HTTP2 stream-ids must be monotonically increasing, if we want to -- support multi-threaded clients we need to serialize access to a -- critical region of the code when clients send HEADERS+CONTINUATIONs -- frames. -- -- Passing the Http2Stream object as part of the callback avoids -- leaking the implementation of the critical region, meanwhile, the -- StreamDefinition delimits this critical region. type StreamStarter a = (Http2Stream -> StreamDefinition a) -> IO (Either TooMuchConcurrency a) -- | Whether or not the client library believes the server will reject the -- new stream. The Int content corresponds to the number of streams that -- should end before accepting more streams. A reason this number can be -- more than zero is that servers can change (and hence reduce) the -- advertised number of allowed maxConcurrentStreams at any time. newtype TooMuchConcurrency TooMuchConcurrency :: Int -> TooMuchConcurrency [_getStreamRoomNeeded] :: TooMuchConcurrency -> Int -- | Opaque proof that a client stream was initialized. -- -- This type is only useful to force calling _headers in -- _initStream and contains no information. data StreamThread -- | Record holding functions one can call while in an HTTP2 client stream. data Http2Stream Http2Stream :: (HeaderList -> (FrameFlags -> FrameFlags) -> IO StreamThread) -> (Priority -> IO ()) -> (ErrorCodeId -> IO ()) -> IO (FrameHeader, StreamId, Either ErrorCode HeaderList) -> IO (FrameHeader, Either ErrorCode ByteString) -> ((FrameFlags -> FrameFlags) -> ByteString -> IO ()) -> (PushPromiseHandler -> IO ()) -> Http2Stream -- | Starts the stream with HTTP headers. Flags modifier can use -- setEndStream if no data is required passed the last block of -- headers. Usually, this is the only call needed to build an -- _initStream. [_headers] :: Http2Stream -> HeaderList -> (FrameFlags -> FrameFlags) -> IO StreamThread -- | Changes the PRIORITY of this stream. [_prio] :: Http2Stream -> Priority -> IO () -- | Resets this stream with a RST frame. You should not use this stream -- past this call. [_rst] :: Http2Stream -> ErrorCodeId -> IO () -- | Waits for HTTP headers from the server. This function also passes the -- last frame header of the PUSH-PROMISE, HEADERS, or CONTINUATION -- sequence of frames. Waiting more than once per stream will hang as -- headers are sent only one time. [_waitHeaders] :: Http2Stream -> IO (FrameHeader, StreamId, Either ErrorCode HeaderList) -- | Waits for a DATA frame chunk. A user should testEndStream on the frame -- header to know when the server is done with the stream. [_waitData] :: Http2Stream -> IO (FrameHeader, Either ErrorCode ByteString) -- | Sends a DATA frame chunk. You can use send empty frames with only -- headers modifiers to close streams. This function is oblivious to -- framing and hence does not respect the RFC if sending large blocks. -- Use sendData to chunk and send naively according to server's -- preferences. This function can be useful if you intend to handle the -- framing yourself. [_sendDataChunk] :: Http2Stream -> (FrameFlags -> FrameFlags) -> ByteString -> IO () [_waitPushPromise] :: Http2Stream -> PushPromiseHandler -> IO () -- | Offers credit-based flow-control. -- -- Any mutable changes are atomic and hence work as intended in a -- multithreaded setup. -- -- The design of the flow-control mechanism is subject to changes. One -- important thing to keep in mind with current implementation is that -- both the connection and streams are credited with _addCredit as -- soon as DATA frames arrive, hence no-need to account for the DATA -- frames (but you can account for delay-bandwidth product for instance). data IncomingFlowControl IncomingFlowControl :: (WindowSize -> IO ()) -> (WindowSize -> IO Int) -> IO Bool -> IncomingFlowControl -- | Add credit (using a hidden mutable reference underneath). This -- function only does accounting, the IO only does mutable changes. See -- _updateWindow. [_addCredit] :: IncomingFlowControl -> WindowSize -> IO () -- | Consumes some credit and returns the credit left. [_consumeCredit] :: IncomingFlowControl -> WindowSize -> IO Int -- | Sends a WINDOW_UPDATE frame crediting it with the whole amount -- credited since the last _updateWindow call. The boolean tells whether -- an update was actually sent or not. A reason for not sending an update -- is if there is no credit in the flow-control system. [_updateWindow] :: IncomingFlowControl -> IO Bool -- | Receives credit-based flow-control or block. -- -- There is no way to observe the total amount of credit and -- receive/withdraw are atomic hence this object is thread-safe. However -- we plan to propose an STM-based API to allow withdrawing atomically -- from both the connection and a per-stream OutgoingFlowControl -- objects at a same time. Without such atomicity one must ensure -- consumers do not exhaust the connection credit before taking the -- per-stream credit (else they might prevent others sending data without -- taking any). -- -- Longer term we plan to hide outgoing-flow-control increment/decrement -- altogether because exception between withdrawing credit and sending -- DATA could mean lost credit (and hence hanging streams). data OutgoingFlowControl OutgoingFlowControl :: (WindowSize -> IO ()) -> (WindowSize -> IO WindowSize) -> OutgoingFlowControl -- | Add credit (using a hidden mutable reference underneath). [_receiveCredit] :: OutgoingFlowControl -> WindowSize -> IO () -- | Wait until we can take credit from stash. The returned value -- correspond to the amount that could be withdrawn, which is -- min(current, wanted). A caller should withdraw credit to send DATA -- chunks and put back any unused credit with _receiveCredit. [_withdrawCredit] :: OutgoingFlowControl -> WindowSize -> IO WindowSize -- | Type synonym for functions that modify flags. -- -- Typical FlagSetter for library users are HTTP2.setEndHeader when -- sending headers HTTP2.setEndStream to signal that there the client is -- not willing to send more data. -- -- We might use Endo in the future. type FlagSetter = FrameFlags -> FrameFlags -- | Prepares a client around a frame connection. -- -- This is mostly useful if you want to muck around the -- Http2FrameConnection (e.g., for tracing frames) as well as for unit -- testing purposes. If you want to create a new connection you should -- likely use newHttp2Client instead. wrapFrameClient :: Http2FrameConnection -> Int -> Int -> SettingsList -> IO Http2Client -- | Synonym of _goaway. -- -- https://github.com/http2/http2-spec/pull/366 _gtfo :: Http2Client -> ErrorCodeId -> ByteString -> IO () instance GHC.Show.Show Network.HTTP2.Client.TooMuchConcurrency -- | A toolbox with high-level functions to interact with an established -- HTTP2 conection. -- -- These helpers make the assumption that you want to work in a -- multi-threaded environment and that you want to send and receiving -- whole HTTP requests at once (i.e., you do not care about streaming -- individual HTTP requests/responses but want to make many requests). module Network.HTTP2.Client.Helpers -- | Uploads a whole HTTP body at a time. -- -- This function should be called at most once per stream. This function -- closes the stream with HTTP2.setEndStream chunk at the end. If you -- want to post data (e.g., streamed chunks) your way to avoid loading a -- whole bytestring in RAM, please study the source code of this function -- first. -- -- This function sends one chunk at a time respecting by preference: - -- server's flow control desires - server's chunking preference -- -- Uploading an empty bytestring will send a single DATA frame with -- setEndStream and no payload. upload :: ByteString -> Http2Client -> OutgoingFlowControl -> Http2Stream -> OutgoingFlowControl -> IO () -- | Wait for a stream until completion. -- -- This function is fine if you don't want to consume results in chunks. -- See fromStreamResult to collect the complicated -- StreamResult into a simpler StramResponse. waitStream :: Http2Stream -> IncomingFlowControl -> IO StreamResult -- | Converts a StreamResult to a StramResponse, stopping at the first -- error using the `Either HTTP2.ErrorCode` monad. fromStreamResult :: StreamResult -> Either ErrorCode StreamResponse -- | Sequentially wait for every push-promise with a handler. -- -- This function runs forever and you should wrap it with -- withAsync. onPushPromise :: Http2Stream -> PushPromiseHandler -> IO () -- | Result containing the unpacked headers and all frames received in on a -- stream. See StreamResponse and fromStreamResult to get a -- higher-level utility. type StreamResult = (Either ErrorCode HeaderList, [Either ErrorCode ByteString]) -- | An HTTP2 response, once fully received, is made of headers and a -- payload. type StreamResponse = (HeaderList, ByteString) -- | Performs a ping and waits for a reply up to a given timeout (in -- microseconds). ping :: Http2Client -> Int -> ByteString -> IO PingReply -- | Opaque type to express an action which timed out. data TimedOut -- | Result for a ping. type PingReply = (UTCTime, UTCTime, Either TimedOut (FrameHeader, FramePayload)) instance GHC.Show.Show Network.HTTP2.Client.Helpers.TimedOut