Safe Haskell | None |
---|---|
Language | Haskell2010 |
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 .
- newHttp2Client :: HostName -> PortNumber -> Int -> Int -> ClientParams -> SettingsList -> IO Http2Client
- withHttp2Stream :: Http2Client -> StreamStarter a
- headers :: Http2Stream -> HeaderList -> FlagSetter -> IO StreamThread
- sendData :: Http2Client -> Http2Stream -> FlagSetter -> ByteString -> IO ()
- data Http2Client = Http2Client {
- _ping :: ByteString -> IO (IO (FrameHeader, FramePayload))
- _settings :: SettingsList -> IO (IO (FrameHeader, FramePayload))
- _goaway :: ErrorCodeId -> ByteString -> IO ()
- _startStream :: forall a. StreamStarter a
- _incomingFlowControl :: IncomingFlowControl
- _outgoingFlowControl :: OutgoingFlowControl
- _paylodSplitter :: IO PayloadSplitter
- _asyncs :: !Http2ClientAsyncs
- _close :: IO ()
- type PushPromiseHandler = StreamId -> Http2Stream -> HeaderList -> IncomingFlowControl -> OutgoingFlowControl -> IO ()
- data StreamDefinition a = StreamDefinition {}
- type StreamStarter a = (Http2Stream -> StreamDefinition a) -> IO (Either TooMuchConcurrency a)
- newtype TooMuchConcurrency = TooMuchConcurrency {}
- data StreamThread
- data Http2Stream = Http2Stream {
- _headers :: HeaderList -> (FrameFlags -> FrameFlags) -> IO StreamThread
- _prio :: Priority -> IO ()
- _rst :: ErrorCodeId -> IO ()
- _waitHeaders :: IO (FrameHeader, StreamId, Either ErrorCode HeaderList)
- _waitData :: IO (FrameHeader, Either ErrorCode ByteString)
- _sendDataChunk :: (FrameFlags -> FrameFlags) -> ByteString -> IO ()
- _waitPushPromise :: PushPromiseHandler -> IO ()
- data IncomingFlowControl = IncomingFlowControl {
- _addCredit :: WindowSize -> IO ()
- _consumeCredit :: WindowSize -> IO Int
- _updateWindow :: IO Bool
- data OutgoingFlowControl = OutgoingFlowControl {
- _receiveCredit :: WindowSize -> IO ()
- _withdrawCredit :: WindowSize -> IO WindowSize
- linkHttp2Client :: Http2Client -> IO ()
- type FlagSetter = FrameFlags -> FrameFlags
- data Http2ClientAsyncs = Http2ClientAsyncs {
- _waitSettingsAsync :: Async (FrameHeader, FramePayload)
- _creditFlowsAsync :: Async ()
- _HPACKAsync :: Async ()
- _controlFramesAsync :: Async ()
- _incomingFramesAsync :: Async ()
- wrapFrameClient :: Http2FrameConnection -> Int -> Int -> SettingsList -> IO Http2Client
- _gtfo :: Http2Client -> ErrorCodeId -> ByteString -> IO ()
- module Network.HTTP2.Client.FrameConnection
- module Network.Socket
- module Network.TLS
Basics
:: HostName | Host to connect to. |
-> PortNumber | Port number to connect to (usually 443 on the web). |
-> Int | The buffersize for the Network.HPACK encoder. |
-> Int | The buffersize for the Network.HPACK decoder. |
-> ClientParams | The TLS client parameters (e.g., to allow some certificates). |
-> SettingsList | Initial SETTINGS that are sent as first frame. |
-> IO Http2Client |
Starts a new Http2Client with a remote Host/Port. TLS ClientParams are mandatory because we only support TLS-protected streams for now.
withHttp2Stream :: Http2Client -> StreamStarter a Source #
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.
headers :: Http2Stream -> HeaderList -> FlagSetter -> IO StreamThread Source #
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.
sendData :: Http2Client -> Http2Stream -> FlagSetter -> ByteString -> IO () Source #
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.
Starting streams
data Http2Client Source #
Record holding functions one can call while in an HTTP2 client session.
Http2Client | |
|
type PushPromiseHandler = StreamId -> Http2Stream -> HeaderList -> IncomingFlowControl -> OutgoingFlowControl -> IO () Source #
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).
Starting streams
data StreamDefinition a Source #
Defines a client stream.
Please red the doc for this record fields and then see StreamStarter
.
StreamDefinition | |
|
type StreamStarter a = (Http2Stream -> StreamDefinition a) -> IO (Either TooMuchConcurrency a) Source #
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.
newtype TooMuchConcurrency Source #
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.
data StreamThread Source #
Opaque proof that a client stream was initialized.
This type is only useful to force calling _headers
in _initStream
and
contains no information.
data Http2Stream Source #
Record holding functions one can call while in an HTTP2 client stream.
Http2Stream | |
|
Flow control
data IncomingFlowControl Source #
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).
IncomingFlowControl | |
|
data OutgoingFlowControl Source #
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).
OutgoingFlowControl | |
|
Exceptions
linkHttp2Client :: Http2Client -> IO () Source #
Links all asyncs threads of a client to the current thread.
See link
.
Misc.
type FlagSetter = FrameFlags -> FrameFlags Source #
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.
data Http2ClientAsyncs Source #
Set of Async threads running an Http2Client.
If you add other asyncs here, you should also modify
linkHttp2Client
.
Http2ClientAsyncs | |
|
:: Http2FrameConnection | A frame connection. |
-> Int | The buffersize for the Network.HPACK encoder. |
-> Int | The buffersize for the Network.HPACK decoder. |
-> SettingsList | Initial SETTINGS that are sent as first frame. |
-> IO Http2Client |
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.
_gtfo :: Http2Client -> ErrorCodeId -> ByteString -> IO () Source #
Convenience re-exports
module Network.Socket
module Network.TLS