http-kit 0.3.0 → 0.4.0
raw patch · 5 files changed
+58/−35 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.HTTP.Toolkit: UnexpectedEndOfInput :: ToolkitError
+ Network.HTTP.Toolkit.Error: UnexpectedEndOfInput :: ToolkitError
+ Network.HTTP.Toolkit.Error: catchOnly :: (Eq e, Exception e) => IO a -> e -> IO a -> IO a
Files
- http-kit.cabal +1/−1
- src/Network/HTTP/Toolkit.hs +10/−4
- src/Network/HTTP/Toolkit/Body.hs +32/−27
- src/Network/HTTP/Toolkit/Connection.hs +8/−2
- src/Network/HTTP/Toolkit/Error.hs +7/−1
http-kit.cabal view
@@ -1,5 +1,5 @@ name: http-kit-version: 0.3.0+version: 0.4.0 synopsis: A low-level HTTP library description: A low-level HTTP library that can be used to build more sophisticated applications on top of it.
src/Network/HTTP/Toolkit.hs view
@@ -1,6 +1,15 @@ module Network.HTTP.Toolkit (+-- * Exceptions+-- |+-- * All functions that consume input fail with `UnexpectedEndOfInput` if the+-- input ends before the function can completely successfully.+--+-- * All cases where a function may fail with an exception other than+-- @UnexpectedEndOfInput@ are documented thoroughly on a per function level.+--+ ToolkitError(..) -- * Connection- Connection+, Connection , makeConnection , connectionFromHandle @@ -22,9 +31,6 @@ , BodyReader , sendBody , consumeBody---- * Error type-, ToolkitError(..) ) where import Network.HTTP.Toolkit.Body
src/Network/HTTP/Toolkit/Body.hs view
@@ -124,8 +124,9 @@ if done then return "" else do- xs <- connectionRead c- when (B.null xs) $ writeIORef ref True+ xs <- connectionRead c `catchOnly` UnexpectedEndOfInput $ do+ writeIORef ref True+ return "" return xs -- | Create a reader for bodies with a specified length.@@ -158,32 +159,36 @@ makeChunkedReader :: Connection -> IO BodyReader makeChunkedReader conn = do ref <- newIORef (More 0 Data)- return $ do- c <- readIORef ref- case c of- More 0 Data -> do- (n, xs) <- readChunkSize conn- writeIORef ref (More n Extension)- return xs- More n Extension -> do- bs <- connectionRead conn- case breakOnNewline bs of- ("", _) ->- if n > 0- then do- handleChunkData ref (n + 3) bs- else do- writeIORef ref Trailer- connectionUnread conn bs- readTrailer ref- (xs, ys) -> do- connectionUnread conn ys- return xs- More n Data -> do- connectionRead conn >>= handleChunkData ref n- Trailer -> readTrailer ref- Done -> return ""+ return $ go ref `catchOnly` UnexpectedEndOfInput $ do+ writeIORef ref Done+ return "" where+ go ref = do+ c <- readIORef ref+ case c of+ More 0 Data -> do+ (n, xs) <- readChunkSize conn+ writeIORef ref (More n Extension)+ return xs+ More n Extension -> do+ bs <- connectionRead conn+ case breakOnNewline bs of+ ("", _) ->+ if n > 0+ then do+ handleChunkData ref (n + 3) bs+ else do+ writeIORef ref Trailer+ connectionUnread conn bs+ readTrailer ref+ (xs, ys) -> do+ connectionUnread conn ys+ return xs+ More n Data -> do+ connectionRead conn >>= handleChunkData ref n+ Trailer -> readTrailer ref+ Done -> return ""+ handleChunkData :: IORef State -> Int -> ByteString -> IO ByteString handleChunkData ref n bs = do let (xs, ys) = B.splitAt n bs
src/Network/HTTP/Toolkit/Connection.hs view
@@ -8,12 +8,15 @@ ) where import Prelude hiding (read)-import Control.Monad (join, unless)+import Control.Monad (join, when, unless)+import Control.Exception import System.IO (Handle) import Data.IORef import Data.ByteString (ByteString) import qualified Data.ByteString as B +import Network.HTTP.Toolkit.Error+ -- | An abstract connection type that allows to read and unread input. data Connection = Connection { _read :: IO ByteString@@ -37,7 +40,10 @@ -- | Read some input. connectionRead :: Connection -> IO ByteString-connectionRead = _read+connectionRead c = do+ bs <- _read c+ when (B.null bs) $ throwIO UnexpectedEndOfInput+ return bs -- | Push back some input. The pushed back input will be returned by a later -- call to `connectionRead`.
src/Network/HTTP/Toolkit/Error.hs view
@@ -2,12 +2,15 @@ module Network.HTTP.Toolkit.Error where import Data.Typeable+import Control.Monad (guard) import Control.Exception import Data.ByteString (ByteString) data ToolkitError =+ -- | The input ended unpexpectedly while reading a message.+ UnexpectedEndOfInput -- | The request-line of the message is malformed.- InvalidRequestLine ByteString+ | InvalidRequestLine ByteString -- | The status-line of the message is malformed. | InvalidStatusLine ByteString -- | A header field is malformed.@@ -23,3 +26,6 @@ deriving (Eq, Show, Typeable) instance Exception ToolkitError++catchOnly :: (Eq e, Exception e) => IO a -> e -> IO a -> IO a+(action `catchOnly` e) handler = catchJust (guard . (== e)) action $ \() -> handler