{-# LANGUAGE OverloadedStrings #-} module Network.HTTP.Toolkit.Request ( RequestPath , RequestHeader , readRequest , readRequestWithLimit , parseRequestLine , determineRequestBodyType ) where import Control.Applicative import Control.Monad (join) import Control.Exception import Data.Maybe import Data.Traversable (sequenceA) import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import Network.HTTP.Types import Network.HTTP.Toolkit.Error import Network.HTTP.Toolkit.Connection import Network.HTTP.Toolkit.Header import Network.HTTP.Toolkit.Body type RequestPath = ByteString type RequestHeader = MessageHeader (Method, RequestPath) -- | Same as `readRequestWithLimit` with a `Limit` of `defaultHeaderSizeLimit`. readRequest :: Connection -> IO (RequestHeader, BodyReader) readRequest = readRequestWithLimit defaultHeaderSizeLimit -- | Read request from provided connection. -- -- Throws: -- -- * `InvalidRequestLine` if request-line is malformed. -- -- * `HeaderTooLarge` if the header size exceeds the specified `Limit`. -- -- * `InvalidHeader` if header is malformed. readRequestWithLimit :: Limit -> Connection -> IO (RequestHeader, BodyReader) readRequestWithLimit limit c = do r@(MessageHeader _ headers) <- join $ sequenceA . fmap parseRequestLine_ <$> readMessageHeaderWithLimit limit c (,) r <$> makeBodyReader c (determineRequestBodyType headers) parseRequestLine_ :: ByteString -> IO (Method, ByteString) parseRequestLine_ input = maybe (throwIO $ InvalidRequestLine input) return (parseRequestLine input) -- | Parse request-line (see ). parseRequestLine :: ByteString -> Maybe (Method, RequestPath) parseRequestLine input = case B.words input of method : path : _ -> Just (method, path) _ -> Nothing -- | Determine the message `BodyType` from a given list of message headers (as -- of ). determineRequestBodyType :: [Header] -> BodyType determineRequestBodyType = fromMaybe None . bodyTypeFromHeaders