-- 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.10.0.0 module Network.HTTP2.Client.Exceptions type ClientIO = ExceptT ClientError IO -- | A set of errors as observed from the client. data ClientError -- | We received a TCP end-of-stream and there will be no further read-IOs -- possible on the connection. EarlyEndOfStream :: ClientError runClientIO :: ClientIO a -> IO (Either ClientError a) -- | Lift a computation from the argument monad to the constructed monad. lift :: (MonadTrans t, Monad m) => m a -> t m a -- | A monad transformer that adds exceptions to other monads. -- -- ExceptT constructs a monad parameterized over two things: -- -- -- -- The return function yields a computation that produces the -- given value, while >>= sequences two subcomputations, -- exiting on the first exception. data ExceptT e (m :: Type -> Type) a -- | Is used within a monadic computation to begin exception processing. throwError :: MonadError e m => e -> m a -- | The inverse of ExceptT. runExceptT :: ExceptT e m a -> m (Either e a) instance GHC.Classes.Eq Network.HTTP2.Client.Exceptions.ClientError instance GHC.Classes.Ord Network.HTTP2.Client.Exceptions.ClientError instance GHC.Show.Show Network.HTTP2.Client.Exceptions.ClientError instance GHC.Exception.Type.Exception Network.HTTP2.Client.Exceptions.ClientError module Network.HTTP2.Client.RawConnection data RawHttp2Connection RawHttp2Connection :: ([ByteString] -> ClientIO ()) -> (Int -> ClientIO ByteString) -> ClientIO () -> RawHttp2Connection -- | Function to send raw data to the server. [_sendRaw] :: RawHttp2Connection -> [ByteString] -> ClientIO () -- | Function to block reading a datachunk of a given size from the server. -- An empty chunk when asking for a length larger than 0 means the -- underlying network session is closed. A compliant HTP2 server should -- have sent a GOAWAY before such an event occurs. [_nextRaw] :: RawHttp2Connection -> Int -> ClientIO ByteString [_close] :: RawHttp2Connection -> ClientIO () -- | Initiates a RawHttp2Connection with a server. -- -- The current code does not handle closing the connexion, yikes. newRawHttp2Connection :: HostName -> PortNumber -> Maybe ClientParams -> ClientIO RawHttp2Connection -- | Initiates a RawHttp2Connection with a unix domain socket. -- -- The current code does not handle closing the connexion, yikes. newRawHttp2ConnectionUnix :: String -> Maybe ClientParams -> ClientIO RawHttp2Connection -- | Initiates a RawHttp2Connection with a server over a connected socket. -- -- The current code does not handle closing the connexion, yikes. Since -- 0.8.0.2 newRawHttp2ConnectionSocket :: Socket -> Maybe ClientParams -> ClientIO RawHttp2Connection module Network.HTTP2.Client.FrameConnection data Http2FrameConnection Http2FrameConnection :: (StreamId -> Http2FrameClientStream) -> Http2ServerStream -> ClientIO () -> 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 -> ClientIO () -- | Creates a new Http2FrameConnection to a given host for a -- frame-to-frame communication. newHttp2FrameConnection :: HostName -> PortNumber -> Maybe ClientParams -> ClientIO Http2FrameConnection -- | Adds framing around a RawHttp2Connection. frameHttp2RawConnection :: RawHttp2Connection -> ClientIO Http2FrameConnection data Http2ServerStream Http2ServerStream :: ClientIO (FrameHeader, Either HTTP2Error FramePayload) -> Http2ServerStream [_nextHeaderAndFrame] :: Http2ServerStream -> ClientIO (FrameHeader, Either HTTP2Error FramePayload) data Http2FrameClientStream Http2FrameClientStream :: (ClientIO [(FrameFlags -> FrameFlags, FramePayload)] -> ClientIO ()) -> 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 -> ClientIO [(FrameFlags -> FrameFlags, FramePayload)] -> ClientIO () [_getStreamId] :: Http2FrameClientStream -> StreamId -- | Creates a client stream. makeFrameClientStream :: Http2FrameConnection -> StreamId -> Http2FrameClientStream -- | Sends a frame to the server. sendOne :: Http2FrameClientStream -> (FrameFlags -> FrameFlags) -> FramePayload -> ClientIO () -- | Sends multiple back-to-back frames to the server. sendBackToBack :: Http2FrameClientStream -> [(FrameFlags -> FrameFlags, FramePayload)] -> ClientIO () -- | Waits for the next frame from the server. next :: Http2FrameConnection -> ClientIO (FrameHeader, Either HTTP2Error FramePayload) -- | Closes the Http2FrameConnection abruptly. closeConnection :: Http2FrameConnection -> ClientIO () -- | 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 around a frame connection. -- -- This function is slightly safer than startHttp2Client because -- it uses withAsync instead of async; plus this function -- calls linkAsyncs to make sure that a network error kills the -- controlling thread. However, this with-pattern takes the control of -- the thread and can be annoying at times. -- -- This function tries to finalize the client with a call to -- _close, a second call to _close will trigger an -- IOException because the Handle representing the TCP connection will be -- closed. runHttp2Client :: Http2FrameConnection -> Int -> Int -> SettingsList -> GoAwayHandler -> FallBackFrameHandler -> (Http2Client -> ClientIO a) -> ClientIO a -- | Starts a new Http2Client around a frame connection. -- -- You may want to linkAsyncs for a proper and automated cleanup -- of the underlying threads. newHttp2Client :: Http2FrameConnection -> Int -> Int -> SettingsList -> GoAwayHandler -> FallBackFrameHandler -> ClientIO 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 -> ClientIO StreamThread -- | Sends HTTP trailers. -- -- Trailers should be the last thing sent over a stream. trailers :: Http2Stream -> HeaderList -> (FrameFlags -> FrameFlags) -> ClientIO () -- | 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 -> ClientIO () -- | Record holding functions one can call while in an HTTP2 client -- session. data Http2Client Http2Client :: (ByteString -> ClientIO (ClientIO (FrameHeader, FramePayload))) -> (SettingsList -> ClientIO (ClientIO (FrameHeader, FramePayload))) -> (ErrorCodeId -> ByteString -> ClientIO ()) -> (forall a. StreamStarter a) -> IncomingFlowControl -> OutgoingFlowControl -> IO PayloadSplitter -> !Http2ClientAsyncs -> ClientIO () -> 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 -> ClientIO (ClientIO (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 -> ClientIO (ClientIO (FrameHeader, FramePayload)) -- | Sends a GOAWAY. [_goaway] :: Http2Client -> ErrorCodeId -> ByteString -> ClientIO () -- | 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. [_payloadSplitter] :: Http2Client -> IO PayloadSplitter -- | Asynchronous operations threads. [_asyncs] :: Http2Client -> !Http2ClientAsyncs -- | Immediately stop processing incoming frames and closes the network -- connection. [_close] :: Http2Client -> ClientIO () -- | 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 -> ClientIO () -- | Defines a client stream. -- -- Please red the doc for this record fields and then see -- StreamStarter. data StreamDefinition a StreamDefinition :: ClientIO StreamThread -> (IncomingFlowControl -> OutgoingFlowControl -> ClientIO 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 -> ClientIO 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 -> ClientIO 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) -> ClientIO (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) -> ClientIO StreamThread) -> (Priority -> ClientIO ()) -> (ErrorCodeId -> ClientIO ()) -> ClientIO StreamEvent -> ((FrameFlags -> FrameFlags) -> ByteString -> ClientIO ()) -> (StreamId -> HeaderList -> PushPromiseHandler -> ClientIO ()) -> 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) -> ClientIO StreamThread -- | Changes the PRIORITY of this stream. [_prio] :: Http2Stream -> Priority -> ClientIO () -- | Resets this stream with a RST frame. You should not use this stream -- past this call. [_rst] :: Http2Stream -> ErrorCodeId -> ClientIO () -- | Waits for the next event on the stream. [_waitEvent] :: Http2Stream -> ClientIO StreamEvent -- | 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 -> ClientIO () [_handlePushPromise] :: Http2Stream -> StreamId -> HeaderList -> PushPromiseHandler -> ClientIO () -- | 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) -> ClientIO 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 -> ClientIO 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 -> ClientIO 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 -> ClientIO WindowSize -- | Links all client's asyncs to current thread using: link -- someUnderlyingAsync . linkAsyncs :: Http2Client -> ClientIO () -- | An exception thrown when the server sends a GoAwayFrame. data RemoteSentGoAwayFrame RemoteSentGoAwayFrame :: !StreamId -> !ErrorCodeId -> !ByteString -> RemoteSentGoAwayFrame -- | A Handler for exceptional circumstances. type GoAwayHandler = RemoteSentGoAwayFrame -> ClientIO () -- | Default GoAwayHandler throws a RemoteSentGoAwayFrame in the -- current thread. -- -- A probably sharper handler if you want to abruptly stop any operation -- is to get the ThreadId of the main client thread and using -- throwTo. -- -- There's an inherent race condition when receiving a GoAway frame -- because the server will likely close the connection which will lead to -- TCP errors as well. defaultGoAwayHandler :: GoAwayHandler -- | A fallback handler for frames. type FallBackFrameHandler = (FrameHeader, FramePayload) -> ClientIO () -- | Default FallBackFrameHandler that ignores frames. ignoreFallbackHandler :: FallBackFrameHandler -- | 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 -- | Set of Async threads running an Http2Client. -- -- This asyncs are linked to the thread where the Http2Client is created. -- If you modify this structure to add more Async, please also modify -- linkAsyncs accordingly. data Http2ClientAsyncs Http2ClientAsyncs :: Async (Either ClientError (FrameHeader, FramePayload)) -> Async (Either ClientError ()) -> Http2ClientAsyncs -- | Async waiting for the initial settings ACK. [_waitSettingsAsync] :: Http2ClientAsyncs -> Async (Either ClientError (FrameHeader, FramePayload)) -- | Async responsible for ingesting all frames, increasing the -- maximum-received streamID and starting the frame dispatch. See -- dispatchFrames. [_incomingFramesAsync] :: Http2ClientAsyncs -> Async (Either ClientError ()) -- | Synonym of _goaway. -- -- https://github.com/http2/http2-spec/pull/366 _gtfo :: Http2Client -> ErrorCodeId -> ByteString -> ClientIO () data StreamEvent StreamHeadersEvent :: !FrameHeader -> !HeaderList -> StreamEvent StreamPushPromiseEvent :: !FrameHeader -> !StreamId -> !HeaderList -> StreamEvent StreamDataEvent :: !FrameHeader -> ByteString -> StreamEvent StreamErrorEvent :: !FrameHeader -> ErrorCode -> StreamEvent -- | Either a host name e.g., "haskell.org" or a numeric host -- address string consisting of a dotted decimal IPv4 address or an IPv6 -- address e.g., "192.168.0.1". type HostName = String -- | Port number. Use the Num instance (i.e. use a literal) to -- create a PortNumber value. -- --
--   >>> 1 :: PortNumber
--   1
--   
--   >>> read "1" :: PortNumber
--   1
--   
--   >>> show (12345 :: PortNumber)
--   "12345"
--   
--   >>> 50000 < (51000 :: PortNumber)
--   True
--   
--   >>> 50000 < (52000 :: PortNumber)
--   True
--   
--   >>> 50000 + (10000 :: PortNumber)
--   60000
--   
data PortNumber data ClientParams 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 -> (FrameFlags -> FrameFlags) -> Http2Client -> OutgoingFlowControl -> Http2Stream -> OutgoingFlowControl -> ClientIO () -- | 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 -> PushPromiseHandler -> ClientIO StreamResult -- | Converts a StreamResult to a StramResponse, stopping at the first -- error using the `Either HTTP2.ErrorCode` monad. fromStreamResult :: StreamResult -> Either ErrorCode StreamResponse -- | 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], Maybe HeaderList) -- | An HTTP2 response, once fully received, is made of headers and a -- payload. type StreamResponse = (HeaderList, ByteString, Maybe HeaderList) -- | Performs a ping and waits for a reply up to a given timeout (in -- microseconds). ping :: Http2Client -> Int -> ByteString -> ClientIO 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