http-semantics 0.2.0 → 0.2.1
raw patch · 6 files changed
+86/−6 lines, 6 files
Files
- ChangeLog.md +8/−0
- Network/HTTP/Semantics/FillBuf.hs +38/−2
- Network/HTTP/Semantics/ReadN.hs +4/−0
- Network/HTTP/Semantics/Server.hs +2/−0
- Network/HTTP/Semantics/Types.hs +33/−3
- http-semantics.cabal +1/−1
ChangeLog.md view
@@ -1,5 +1,13 @@ # ChangeLog for http-semantics +## 0.2.1++* Add outBodyCancel to OutBodyIface+ [#11](https://github.com/kazu-yamamoto/http-semantics/pull/11)+* Documentation improvement.+ [#10](https://github.com/kazu-yamamoto/http-semantics/pull/10)+ [#11](https://github.com/kazu-yamamoto/http-semantics/pull/11)+ ## 0.2.0 * Introduce `responseStreamingIface`
Network/HTTP/Semantics/FillBuf.hs view
@@ -16,6 +16,7 @@ fillStreamBodyGetNext, ) where +import Control.Exception (SomeException) import Control.Monad import qualified Data.ByteString as BS import Data.ByteString.Builder (Builder)@@ -29,8 +30,24 @@ ---------------------------------------------------------------- --- type DynaNext = Buffer -> BufferSize -> WindowSize -> IO Next-type DynaNext = Buffer -> Int -> IO Next+-- | Write part of a streaming response to the write buffer+--+-- In @http2@ this will be used to construct a single HTTP2 @DATA@ frame+-- (see discussion of the maximum number of bytes, below).+type DynaNext =+ Buffer+ -- ^ Write buffer+ -> Int+ -- ^ Maximum number of bytes we are allowed to write+ --+ -- In @http2@, this maximum will be set to the space left in the write+ -- buffer. Implicitly this also means that this maximum cannot exceed the+ -- maximum size of a HTTP2 frame, since in @http2@ the size of the write+ -- buffer is also used to set @SETTINGS_MAX_FRAME_SIZE@ (see+ -- @confBufferSize@).+ -> IO Next+ -- ^ Information on the data written, and on how to continue if not all data+ -- was written type BytesFilled = Int @@ -39,12 +56,15 @@ BytesFilled -- payload length Bool -- require flushing (Maybe DynaNext)+ | CancelNext (Maybe SomeException) ---------------------------------------------------------------- data StreamingChunk = -- | Indicate that the stream is finished StreamingFinished (Maybe CleanupStream)+ | -- | Indicate that the stream is cancelled+ StreamingCancelled (Maybe SomeException) | -- | Flush the stream -- -- This will cause the write buffer to be written to the network socket,@@ -124,6 +144,10 @@ ---------------------------------------------------------------- -- | Like 'DynaNext', but with additional argument indicating total bytes written+--+-- Since @http2@ uses @DynaNext@ to construct a /single/ @DATA@ frame, the+-- \"total number of bytes written\" refers to the current size of the payload+-- of that @DATA@ frame. type NextWithTotal = Int -> DynaNext -- | Run the chunk, then continue as specified, unless streaming is finished@@ -131,6 +155,7 @@ runStreamingChunk chunk next = case chunk of StreamingFinished mdec -> finished mdec+ StreamingCancelled mErr -> cancel mErr StreamingFlush -> flush StreamingBuilder builder NotEndOfStream -> runStreamingBuilder builder next StreamingBuilder builder (EndOfStream mdec) -> runStreamingBuilder builder (finished mdec)@@ -143,6 +168,17 @@ flush :: NextWithTotal flush = \total _buf _room -> do return $ Next total True (Just $ next 0)++ -- Cancel streaming+ --+ -- The @_total@ number of bytes written refers to the @DATA@ frame currently+ -- under construction, but not yet sent (see discussion at 'DynaNext' and+ -- 'NextWithTotal'). Moreover, the documentation of 'outBodyCancel'+ -- explicitly states that such a partially constructed frame, if one exists,+ -- will be discarded on cancellation. We can therefore simply ignore+ -- @_total@ here.+ cancel :: Maybe SomeException -> NextWithTotal+ cancel mErr = \_total _buf _room -> pure $ CancelNext mErr -- | Run 'Builder' until completion, then continue as specified runStreamingBuilder :: Builder -> NextWithTotal -> NextWithTotal
Network/HTTP/Semantics/ReadN.hs view
@@ -14,6 +14,10 @@ type ReadN = Int -> IO B.ByteString -- | Naive implementation for readN.+--+-- /NOTE/: This function is intended to be used by a single thread only.+-- (It is probably quite rare anyway to want concurrent reads from the /same/+-- network socket.) defaultReadN :: Socket -> IORef (Maybe B.ByteString) -> ReadN defaultReadN _ _ 0 = return B.empty defaultReadN s ref n = do
Network/HTTP/Semantics/Server.hs view
@@ -80,6 +80,8 @@ -- should give them to the sending function. -- The sending function would throw exceptions so that -- they can be logged.+--+-- The sending function must only be called once. type Server = Request -> Aux -> (Response -> [PushPromise] -> IO ()) -> IO () -- | HTTP/2 push promise or sever push.
Network/HTTP/Semantics/Types.hs view
@@ -26,6 +26,7 @@ Path, ) where +import Control.Exception (SomeException) import Data.ByteString.Builder (Builder) import Data.IORef import Data.Int (Int64)@@ -73,14 +74,43 @@ -- streaming body. , outBodyPush :: Builder -> IO () -- ^ Push a new chunk+ --+ -- In @http2@, there is no direct correspondence between chunks and the+ -- resulting @DATA@ frames sent: the chunks are collected (written to an+ -- internal write buffer) until we can fill a frame.+ --+ -- See also 'outBodyFlush'. , outBodyPushFinal :: Builder -> IO () -- ^ Push the final chunk --- -- Using this function instead of 'outBodyPush' can be used to guarantee that the final- -- HTTP2 DATA frame is marked end-of-stream; with 'outBodyPush' it may happen that- -- an additional empty DATA frame is used for this purpose.+ -- Using this function instead of 'outBodyPush' can be used to guarantee+ -- that the final HTTP2 DATA frame is marked end-of-stream; with+ -- 'outBodyPush' it may happen that an additional empty DATA frame is used+ -- for this purpose. Additionally, after calling this function,+ -- 'outBodyCancel' will be a no-op.+ , outBodyCancel :: Maybe SomeException -> IO ()+ -- ^ Cancel the stream+ --+ -- Sends a @RST_STREAM@ to the peer. If cancelling as the result of an+ -- exception, a 'Just' should be provided which specifies the exception+ -- which will be stored locally as the reason for cancelling the stream; in+ -- this case, the error code sent with the @RST_STREAM@ will be+ -- @INTERNAL_ERROR@ (see+ -- <https://datatracker.ietf.org/doc/html/rfc7540#section-7>). If 'Nothing'+ -- is given, the error code will be @CANCEL@.+ --+ -- If there is a partially constructed @DATA@ frame at the time of+ -- cancellation, this frame is discarded. If this is undesirable, you should+ -- call 'outBodyFlush' prior to cancelling. , outBodyFlush :: IO () -- ^ Flush+ --+ -- This can be used to emit a DATA frame with the data collected so far+ -- (using 'outBodyPush'), even if that DATA frame has not yet reached the+ -- maximum frame size. Calling 'outBodyFlush' unnecessarily can therefore+ -- result in excessive overhead from frame headers.+ --+ -- If no data is available to send, this is a no-op. } -- | Input object
http-semantics.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: http-semantics-version: 0.2.0+version: 0.2.1 license: BSD-3-Clause license-file: LICENSE maintainer: Kazu Yamamoto <kazu@iij.ad.jp>