packages feed

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 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