http2-client 0.2.0.2 → 0.3.0.0
raw patch · 3 files changed
+46/−28 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Network.HTTP2.Client: type PushPromiseHandler = StreamId -> Http2Stream -> IncomingFlowControl -> OutgoingFlowControl -> IO ()
+ Network.HTTP2.Client: type PushPromiseHandler = StreamId -> Http2Stream -> HeaderList -> IncomingFlowControl -> OutgoingFlowControl -> IO ()
Files
- app/Main.hs +2/−2
- http2-client.cabal +1/−1
- src/Network/HTTP2/Client.hs +43/−25
app/Main.hs view
@@ -136,8 +136,8 @@ , (":authority", ByteString.pack _host) ] <> _extraHeaders - let ppHandler _ stream streamFlowControl _ = void $ forkIO $ do- timePrint ("push stream started" :: String)+ let ppHandler _ stream ppHdrs streamFlowControl _ = void $ forkIO $ do+ timePrint ("push stream started" :: String, ppHdrs) waitStream stream streamFlowControl >>= timePrint . fromStreamResult timePrint ("push stream ended" :: String)
http2-client.cabal view
@@ -1,5 +1,5 @@ name: http2-client-version: 0.2.0.2+version: 0.3.0.0 synopsis: A native HTTP2 client library. description: Please read the README.md at the homepage. homepage: https://github.com/lucasdicioccio/http2-client
src/Network/HTTP2/Client.hs view
@@ -227,7 +227,7 @@ -- 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 -> IncomingFlowControl -> OutgoingFlowControl -> IO ()+ StreamId -> Http2Stream -> HeaderList -> IncomingFlowControl -> OutgoingFlowControl -> IO () -- | Helper to carry around the HPACK encoder for outgoing header blocks.. data HpackEncoderContext = HpackEncoderContext {@@ -411,9 +411,9 @@ :: Exception e => Http2FrameConnection -> IORef ConnectionSettings- -> Chan (FrameHeader, Either e FramePayload)- -> Chan (FrameHeader, StreamId, Either ErrorCode HeaderList)- -> Chan (StreamId, Chan (FrameHeader, Either e FramePayload), StreamId)+ -> FramesChan e+ -> HeadersChan+ -> PushPromisesChan e -> HpackEncoderContext -> StreamId -> (Http2Stream -> StreamDefinition a)@@ -450,12 +450,12 @@ let _rst = sendResetFrame frameStream let _prio = sendPriorityFrame frameStream let _waitPushPromise ppHandler = do- (_,ppFrames,ppSid) <- waitPushPromiseWithParentStreamId sid pushPromises- let mkStreamActions stream = StreamDefinition (return CST) (ppHandler sid stream)+ (_,ppFrames,ppHeaders,ppSid,ppReadHeaders) <- waitPushPromiseWithParentStreamId sid pushPromises+ let mkStreamActions stream = StreamDefinition (return CST) (ppHandler sid stream ppReadHeaders) ppCont <- initializeStream conn settings ppFrames- serverHeaders+ ppHeaders serverPushPromises hpackEncoder ppSid@@ -534,11 +534,20 @@ _ <- _consumeCredit flowControl (HTTP2.payloadLength fh) _addCredit flowControl (HTTP2.payloadLength fh) +data HPACKLoopDecision =+ ForwardHeader !StreamId+ | OpenPushPromise !StreamId !StreamId++type FramesChan e = Chan (FrameHeader, Either e FramePayload)+type HeadersChan = Chan (FrameHeader, StreamId, Either ErrorCode HeaderList)+type PushPromisesChanContent e = (StreamId, FramesChan e, HeadersChan, StreamId, HeaderList)+type PushPromisesChan e = Chan (PushPromisesChanContent e)+ incomingHPACKFramesLoop :: Exception e- => Chan (FrameHeader, Either e FramePayload)- -> Chan (FrameHeader, StreamId, Either ErrorCode HeaderList)- -> Chan (StreamId, Chan (FrameHeader, Either e FramePayload), StreamId)+ => FramesChan e+ -> HeadersChan+ -> PushPromisesChan e -> DynamicTable -> IO () incomingHPACKFramesLoop frames hdrs pushPromises hpackDecoder = forever $ do@@ -547,18 +556,14 @@ , FrameHeaders ] frames- (sId, pattern) <- case fp of- PushPromiseFrame sid hbf -> do- -- Important: We duplicate the channel here or we risk losing- -- DATA frames sent over the stream.- ppChan <- dupChan frames- let parentSid = HTTP2.streamId fh- writeChan pushPromises (parentSid, ppChan, sid)- return (sid, Right hbf)+ let sid = HTTP2.streamId fh+ (decision, pattern) <- case fp of+ PushPromiseFrame ppSid hbf -> do+ return (OpenPushPromise sid ppSid, Right hbf) HeadersFrame _ hbf -> -- TODO: handle priority- return (HTTP2.streamId fh, Right hbf)+ return (ForwardHeader sid, Right hbf) RSTStreamFrame err ->- return (HTTP2.streamId fh, Left err)+ return (ForwardHeader sid, Left err) _ -> error "wrong TypeId" let go curFh (Right buffer) =@@ -576,10 +581,23 @@ _ -> error "waitFrameWithTypeIdForStreamId returned an unknown frame" else do newHdrs <- decodeHeader hpackDecoder buffer- writeChan hdrs (curFh, sId, Right newHdrs)+ case decision of+ ForwardHeader sId ->+ writeChan hdrs (curFh, sId, Right newHdrs)+ OpenPushPromise parentSid newSid -> do+ -- Important: We duplicate the channel here or we risk+ -- losing DATA or HEADERS+CONTINUATION frames sent over+ -- the main stream because even though+ -- 'initializeStream' dupes frame channels, this+ -- function will has no guarantee that the parent+ -- stream and the push-promise handler that will+ -- initiate the new stream are synchronous.+ ppChan <- dupChan frames+ ppHeaders <- dupChan hdrs+ writeChan pushPromises (parentSid, ppChan, ppHeaders, newSid, newHdrs) go curFh (Left err) =- writeChan hdrs (curFh, sId, (Left $ HTTP2.fromErrorCodeId err))+ writeChan hdrs (curFh, sid, (Left $ HTTP2.fromErrorCodeId err)) go fh pattern @@ -835,13 +853,13 @@ waitPushPromiseWithParentStreamId :: StreamId- -> Chan (StreamId, Chan (FrameHeader, Either e0 FramePayload), StreamId)- -> IO (StreamId, Chan (FrameHeader, Either e0 FramePayload), StreamId)+ -> PushPromisesChan e+ -> IO (PushPromisesChanContent e) waitPushPromiseWithParentStreamId sid chan = loop where loop = do- tuple@(parentSid,_,_) <- readChan chan+ tuple@(parentSid,_,_,_,_) <- readChan chan if parentSid == sid then return tuple else loop