http2-client 0.10.0.0 → 0.10.0.1
raw patch · 9 files changed
+69/−47 lines, 9 filesdep ~asyncdep ~basedep ~bytestringPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: async, base, bytestring, containers, deepseq, http2, mtl, network, stm, time, tls
API changes (from Hackage documentation)
- Network.HTTP2.Client: 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
+ Network.HTTP2.Client: Http2Client :: (ByteString -> ClientIO (ClientIO (FrameHeader, FramePayload))) -> (SettingsList -> ClientIO (ClientIO (FrameHeader, FramePayload))) -> (ErrorCode -> ByteString -> ClientIO ()) -> (forall a. StreamStarter a) -> IncomingFlowControl -> OutgoingFlowControl -> IO PayloadSplitter -> !Http2ClientAsyncs -> ClientIO () -> Http2Client
- Network.HTTP2.Client: Http2Stream :: (HeaderList -> (FrameFlags -> FrameFlags) -> ClientIO StreamThread) -> (Priority -> ClientIO ()) -> (ErrorCodeId -> ClientIO ()) -> ClientIO StreamEvent -> ((FrameFlags -> FrameFlags) -> ByteString -> ClientIO ()) -> (StreamId -> HeaderList -> PushPromiseHandler -> ClientIO ()) -> Http2Stream
+ Network.HTTP2.Client: Http2Stream :: (HeaderList -> (FrameFlags -> FrameFlags) -> ClientIO StreamThread) -> (Priority -> ClientIO ()) -> (ErrorCode -> ClientIO ()) -> ClientIO StreamEvent -> ((FrameFlags -> FrameFlags) -> ByteString -> ClientIO ()) -> (StreamId -> HeaderList -> PushPromiseHandler -> ClientIO ()) -> Http2Stream
- Network.HTTP2.Client: RemoteSentGoAwayFrame :: !StreamId -> !ErrorCodeId -> !ByteString -> RemoteSentGoAwayFrame
+ Network.HTTP2.Client: RemoteSentGoAwayFrame :: !StreamId -> !ErrorCode -> !ByteString -> RemoteSentGoAwayFrame
- Network.HTTP2.Client: [_goaway] :: Http2Client -> ErrorCodeId -> ByteString -> ClientIO ()
+ Network.HTTP2.Client: [_goaway] :: Http2Client -> ErrorCode -> ByteString -> ClientIO ()
- Network.HTTP2.Client: [_rst] :: Http2Stream -> ErrorCodeId -> ClientIO ()
+ Network.HTTP2.Client: [_rst] :: Http2Stream -> ErrorCode -> ClientIO ()
- Network.HTTP2.Client: _gtfo :: Http2Client -> ErrorCodeId -> ByteString -> ClientIO ()
+ Network.HTTP2.Client: _gtfo :: Http2Client -> ErrorCode -> ByteString -> ClientIO ()
- Network.HTTP2.Client: data ClientParams
+ Network.HTTP2.Client: data () => ClientParams
- Network.HTTP2.Client: data PortNumber
+ Network.HTTP2.Client: data () => PortNumber
- Network.HTTP2.Client.Exceptions: data ExceptT e (m :: Type -> Type) a
+ Network.HTTP2.Client.Exceptions: data () => ExceptT e (m :: Type -> Type) a
- Network.HTTP2.Client.FrameConnection: Http2ServerStream :: ClientIO (FrameHeader, Either HTTP2Error FramePayload) -> Http2ServerStream
+ Network.HTTP2.Client.FrameConnection: Http2ServerStream :: ClientIO (FrameHeader, Either FrameDecodeError FramePayload) -> Http2ServerStream
- Network.HTTP2.Client.FrameConnection: [_nextHeaderAndFrame] :: Http2ServerStream -> ClientIO (FrameHeader, Either HTTP2Error FramePayload)
+ Network.HTTP2.Client.FrameConnection: [_nextHeaderAndFrame] :: Http2ServerStream -> ClientIO (FrameHeader, Either FrameDecodeError FramePayload)
- Network.HTTP2.Client.FrameConnection: next :: Http2FrameConnection -> ClientIO (FrameHeader, Either HTTP2Error FramePayload)
+ Network.HTTP2.Client.FrameConnection: next :: Http2FrameConnection -> ClientIO (FrameHeader, Either FrameDecodeError FramePayload)
- Network.HTTP2.Client.Helpers: waitStream :: Http2Stream -> IncomingFlowControl -> PushPromiseHandler -> ClientIO StreamResult
+ Network.HTTP2.Client.Helpers: waitStream :: Http2Client -> Http2Stream -> IncomingFlowControl -> PushPromiseHandler -> ClientIO StreamResult
Files
- ChangeLog.md +3/−0
- http2-client.cabal +12/−12
- src/Network/HTTP2/Client.hs +14/−14
- src/Network/HTTP2/Client/Channels.hs +5/−3
- src/Network/HTTP2/Client/Dispatch.hs +3/−3
- src/Network/HTTP2/Client/Exceptions.hs +3/−1
- src/Network/HTTP2/Client/FrameConnection.hs +6/−6
- src/Network/HTTP2/Client/Helpers.hs +22/−7
- src/Network/HTTP2/Client/RawConnection.hs +1/−1
ChangeLog.md view
@@ -2,6 +2,9 @@ ## Unreleased changes +- Change `waitStream` so that it automatically credits the connection. This+ is a breaking change due to function signature change.+ ## v0.10.0.0 - Export frameHttp2RawConnection to convert an RawHttp2Connection into an Http2FrameConnection.
http2-client.cabal view
@@ -1,5 +1,5 @@ name: http2-client-version: 0.10.0.0+version: 0.10.0.1 synopsis: A native HTTP2 client library. description: Please read the README.md at the homepage. homepage: https://github.com/lucasdicioccio/http2-client@@ -22,19 +22,19 @@ , Network.HTTP2.Client.RawConnection other-modules: Network.HTTP2.Client.Channels , Network.HTTP2.Client.Dispatch- build-depends: base >= 4.7 && < 5- , async >= 2.1 && < 3- , bytestring >= 0.10 && < 1- , containers >= 0.5 && < 1- , deepseq >= 1.4 && < 2- , http2 >= 1.6 && < 2.1+ build-depends: base >= 4.7 && < 4.20+ , async >= 2.1 && < 2.3+ , bytestring >= 0.11 && < 0.13+ , containers >= 0.5 && < 0.8+ , deepseq >= 1.4 && < 1.6+ , http2 >= 4.1 && < 5 , lifted-async >= 0.10 && < 0.11 , lifted-base >= 0.2 && < 0.3- , mtl >= 2.2 && < 3- , network >= 2.6 && < 4- , stm >= 2.4 && < 3- , time >= 1.8 && < 2- , tls >= 1.4 && < 2+ , mtl >= 2.2 && < 2.4+ , network >= 2.6 && < 3.2+ , stm >= 2.4 && < 2.8+ , time >= 1.8 && < 1.15+ , tls >= 2 && < 2.0.3 , transformers-base >= 0.4 && < 0.5 default-language: Haskell2010
src/Network/HTTP2/Client.hs view
@@ -57,7 +57,7 @@ import Data.IORef.Lifted (newIORef, atomicModifyIORef', readIORef) import Data.Maybe (fromMaybe) import Network.HPACK as HPACK-import Network.HTTP2 as HTTP2+import Network.HTTP2.Frame as HTTP2 import Network.Socket (HostName, PortNumber) import Network.TLS (ClientParams) @@ -166,7 +166,7 @@ -- 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)@.)- , _goaway :: ErrorCodeId -> ByteString -> ClientIO ()+ , _goaway :: ErrorCode -> ByteString -> ClientIO () -- ^ Sends a GOAWAY. , _startStream :: forall a. StreamStarter a -- ^ Spawns new streams. See 'StreamStarter'.@@ -188,7 +188,7 @@ data InitHttp2Client = InitHttp2Client { _initPing :: ByteString -> ClientIO (ClientIO (FrameHeader, FramePayload)) , _initSettings :: SettingsList -> ClientIO (ClientIO (FrameHeader, FramePayload))- , _initGoaway :: ErrorCodeId -> ByteString -> ClientIO ()+ , _initGoaway :: ErrorCode -> ByteString -> ClientIO () , _initStartStream :: forall a. StreamStarter a , _initIncomingFlowControl :: IncomingFlowControl , _initOutgoingFlowControl :: OutgoingFlowControl@@ -224,7 +224,7 @@ -- | Synonym of '_goaway'. -- -- https://github.com/http2/http2-spec/pull/366-_gtfo :: Http2Client -> ErrorCodeId -> ByteString -> ClientIO ()+_gtfo :: Http2Client -> ErrorCode -> ByteString -> ClientIO () _gtfo = _goaway -- | Opaque proof that a client stream was initialized.@@ -243,7 +243,7 @@ -- Usually, this is the only call needed to build an '_initStream'. , _prio :: Priority -> ClientIO () -- ^ Changes the PRIORITY of this stream.- , _rst :: ErrorCodeId -> ClientIO ()+ , _rst :: ErrorCode -> ClientIO () -- ^ Resets this stream with a RST frame. You should not use this stream past this call. , _waitEvent :: ClientIO StreamEvent -- ^ Waits for the next event on the stream.@@ -283,7 +283,7 @@ -- -- Please refer to 'StreamStarter' and 'StreamDefinition' for more. withHttp2Stream :: Http2Client -> StreamStarter a-withHttp2Stream = _startStream+withHttp2Stream client = _startStream client -- | Type synonym for functions that modify flags. --@@ -599,14 +599,14 @@ case payload of (RSTStreamFrame err) -> lift $ do chan <- fmap _streamStateEvents <$> lookupStreamState d sid- let msg = StreamErrorEvent fh (HTTP2.fromErrorCodeId err)+ let msg = StreamErrorEvent fh err maybe (return ()) (flip writeChan msg) chan closeReleaseStream d sid _ -> error $ "expecting RSTFrame but got " ++ show payload dispatchFramesStep- :: (FrameHeader, Either HTTP2Error FramePayload)+ :: (FrameHeader, Either FrameDecodeError FramePayload) -> Dispatch -> ClientIO () dispatchFramesStep (fh,_) d = do@@ -615,7 +615,7 @@ atomicModifyIORef' (_dispatchMaxStreamId d) (\n -> (max n sid, ())) finalizeFramesStep- :: (FrameHeader, Either HTTP2Error FramePayload)+ :: (FrameHeader, Either FrameDecodeError FramePayload) -> Dispatch -> ClientIO () finalizeFramesStep (fh,_) d = do@@ -697,7 +697,7 @@ | OpenPushPromise !StreamId !StreamId data HPACKStepResult =- WaitContinuation !((FrameHeader, Either HTTP2Error FramePayload) -> ClientIO HPACKStepResult)+ WaitContinuation !((FrameHeader, Either FrameDecodeError FramePayload) -> ClientIO HPACKStepResult) | FailedHeaders !FrameHeader !StreamId ErrorCode | FinishedWithHeaders !FrameHeader !StreamId (IO HeaderList) | FinishedWithPushPromise !FrameHeader !StreamId !StreamId (IO HeaderList)@@ -721,7 +721,7 @@ sid :: StreamId sid = HTTP2.streamId fh - go :: FrameHeader -> HPACKLoopDecision -> Either ErrorCodeId ByteString -> HPACKStepResult+ go :: FrameHeader -> HPACKLoopDecision -> Either ErrorCode ByteString -> HPACKStepResult go curFh decision (Right buffer) = if not $ HTTP2.testEndHeader (HTTP2.flags curFh) then WaitContinuation $ \frame -> do@@ -743,7 +743,7 @@ OpenPushPromise parentSid newSid -> FinishedWithPushPromise curFh parentSid newSid (decodeHeader _dispatchHPACKDynamicTable buffer) go curFh _ (Left err) =- FailedHeaders curFh sid (HTTP2.fromErrorCodeId err)+ FailedHeaders curFh sid err newIncomingFlowControl@@ -892,13 +892,13 @@ sendDataFrame s flagmod dat = do sendOne s flagmod (DataFrame dat) -sendResetFrame :: Http2FrameClientStream -> ErrorCodeId -> ClientIO ()+sendResetFrame :: Http2FrameClientStream -> ErrorCode -> ClientIO () sendResetFrame s err = do sendOne s id (RSTStreamFrame err) sendGTFOFrame :: Http2FrameClientStream- -> StreamId -> ErrorCodeId -> ByteString -> ClientIO ()+ -> StreamId -> ErrorCode -> ByteString -> ClientIO () sendGTFOFrame s lastStreamId err errStr = do sendOne s id (GoAwayFrame lastStreamId err errStr)
src/Network/HTTP2/Client/Channels.hs view
@@ -11,10 +11,12 @@ import Control.Concurrent.Chan.Lifted (Chan, readChan, newChan, writeChan) import Control.Exception.Lifted (Exception, throwIO)-import Network.HTTP2 (StreamId, FrameHeader, FramePayload, FrameTypeId, framePayloadToFrameTypeId, streamId)+import Network.HTTP2.Frame (StreamId, FrameHeader, FramePayload, FrameType, FrameDecodeError, framePayloadToFrameType, streamId) import Network.HTTP2.Client.Exceptions +instance Exception FrameDecodeError+ type FramesChan e = Chan (FrameHeader, Either e FramePayload) whenFrame@@ -42,5 +44,5 @@ hasStreamId :: StreamId -> FrameHeader -> FramePayload -> Bool hasStreamId sid h _ = streamId h == sid -hasTypeId :: [FrameTypeId] -> FrameHeader -> FramePayload -> Bool-hasTypeId tids _ p = framePayloadToFrameTypeId p `elem` tids+hasTypeId :: [FrameType] -> FrameHeader -> FramePayload -> Bool+hasTypeId tids _ p = framePayloadToFrameType p `elem` tids
src/Network/HTTP2/Client/Dispatch.hs view
@@ -14,12 +14,12 @@ import GHC.Exception (Exception) import Network.HPACK as HPACK import qualified Network.HPACK.Token as HPACK-import Network.HTTP2 as HTTP2+import Network.HTTP2.Frame as HTTP2 import Network.HTTP2.Client.Channels import Network.HTTP2.Client.Exceptions -type DispatchChan = FramesChan HTTP2Error+type DispatchChan = FramesChan FrameDecodeError -- | A fallback handler for frames. type FallBackFrameHandler = (FrameHeader, FramePayload) -> ClientIO ()@@ -29,7 +29,7 @@ ignoreFallbackHandler = const $ pure () -- | An exception thrown when the server sends a GoAwayFrame.-data RemoteSentGoAwayFrame = RemoteSentGoAwayFrame !StreamId !ErrorCodeId !ByteString+data RemoteSentGoAwayFrame = RemoteSentGoAwayFrame !StreamId !ErrorCode !ByteString deriving Show instance Exception RemoteSentGoAwayFrame
src/Network/HTTP2/Client/Exceptions.hs view
@@ -4,10 +4,12 @@ , ClientError(..) , runClientIO , module Control.Monad.Except+ , module Control.Monad.Trans ) where +import Control.Monad.Trans (lift) import Control.Exception (Exception)-import Control.Monad.Except (ExceptT, runExceptT, throwError, lift)+import Control.Monad.Except (ExceptT, runExceptT, throwError) type ClientIO = ExceptT ClientError IO
src/Network/HTTP2/Client/FrameConnection.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE RankNTypes #-} module Network.HTTP2.Client.FrameConnection ( Http2FrameConnection(..)@@ -22,8 +22,8 @@ import Control.Concurrent.MVar.Lifted (newMVar, takeMVar, putMVar) import Control.Monad ((>=>), void, when) import qualified Data.ByteString as ByteString-import Network.HTTP2 (FrameHeader(..), FrameFlags, FramePayload, HTTP2Error, encodeInfo, decodeFramePayload)-import qualified Network.HTTP2 as HTTP2+import Network.HTTP2.Frame (FrameHeader(..), FrameFlags, FramePayload, FrameDecodeError, encodeInfo, decodeFramePayload)+import qualified Network.HTTP2.Frame as HTTP2 import Network.Socket (HostName, PortNumber) import qualified Network.TLS as TLS @@ -66,11 +66,11 @@ sendBackToBack client payloads = _sendFrames client (pure payloads) data Http2ServerStream = Http2ServerStream {- _nextHeaderAndFrame :: ClientIO (FrameHeader, Either HTTP2Error FramePayload)+ _nextHeaderAndFrame :: ClientIO (FrameHeader, Either FrameDecodeError FramePayload) } -- | Waits for the next frame from the server.-next :: Http2FrameConnection -> ClientIO (FrameHeader, Either HTTP2Error FramePayload)+next :: Http2FrameConnection -> ClientIO (FrameHeader, Either FrameDecodeError FramePayload) next = _nextHeaderAndFrame . _serverStream -- | Adds framing around a 'RawHttp2Connection'.
src/Network/HTTP2/Client/Helpers.hs view
@@ -21,7 +21,7 @@ ) where import Data.Time.Clock (UTCTime, getCurrentTime)-import qualified Network.HTTP2 as HTTP2+import qualified Network.HTTP2.Frame as HTTP2 import qualified Network.HPACK as HPACK import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString@@ -115,12 +115,16 @@ -- -- 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+-- 'StreamResponse'.+waitStream :: Http2Client+ -- ^The connection.+ -> Http2Stream+ -- ^The stream to wait on. This stream must be part of the connection. -> IncomingFlowControl+ -- ^Incoming flow control for the __stream__. -> PushPromiseHandler -> ClientIO StreamResult-waitStream stream streamFlowControl ppHandler = do+waitStream conn stream streamFlowControl ppHandler = do ev <- _waitEvent stream case ev of StreamHeadersEvent fH hdrs@@ -131,10 +135,11 @@ return (Right hdrs, reverse dfrms, trls) StreamPushPromiseEvent _ ppSid ppHdrs -> do _handlePushPromise stream ppSid ppHdrs ppHandler- waitStream stream streamFlowControl ppHandler+ waitStream conn stream streamFlowControl ppHandler _ -> error $ "expecting StreamHeadersEvent but got " ++ show ev where+ connFlowControl = _incomingFlowControl conn waitDataFrames xs = do ev <- _waitEvent stream case ev of@@ -142,9 +147,19 @@ | HTTP2.testEndStream (HTTP2.flags fh) -> return ((Right x):xs, Nothing) | otherwise -> do- _ <- lift $ _consumeCredit streamFlowControl (HTTP2.payloadLength fh)- lift $ _addCredit streamFlowControl (HTTP2.payloadLength fh)+ let size = HTTP2.payloadLength fh+ _ <- lift $ _consumeCredit streamFlowControl size+ lift $ _addCredit streamFlowControl size _ <- _updateWindow $ streamFlowControl+ -- We also send a WINDOW_UPDATE for the connection in order+ -- to not rely on external updateWindow calls. This reduces+ -- latency and makes the function less error-prone to use.+ -- Note that the main loop (dispatchLoop) already credits+ -- the connection for received data frames, but it does not+ -- send the WINDOW_UPDATE frames.. That is why we only send+ -- those frames here, and we do not credit the connection+ -- as we do the stream in the preceding lines.+ _ <- _updateWindow $ connFlowControl waitDataFrames ((Right x):xs) StreamPushPromiseEvent _ ppSid ppHdrs -> do _handlePushPromise stream ppSid ppHdrs ppHandler
src/Network/HTTP2/Client/RawConnection.hs view
@@ -17,7 +17,7 @@ import qualified Data.ByteString as ByteString import Data.ByteString.Lazy (fromChunks) import Data.Monoid ((<>))-import qualified Network.HTTP2 as HTTP2+import qualified Network.HTTP2.Frame as HTTP2 import Network.Socket hiding (recv) import Network.Socket.ByteString import qualified Network.TLS as TLS