X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FPreprocess.hs;h=8e3087ebae70654ae0b4a8f74b5e1f0a4102c466;hp=739dec89f6d6058486a00cf404e7d6a12b7280c9;hb=f402841101b4b84f263eea1a43c848f81c48ff93;hpb=0aa4f6d758fc12fba468f7cd399bbcc48f693d1e diff --git a/Network/HTTP/Lucu/Preprocess.hs b/Network/HTTP/Lucu/Preprocess.hs index 739dec8..8e3087e 100644 --- a/Network/HTTP/Lucu/Preprocess.hs +++ b/Network/HTTP/Lucu/Preprocess.hs @@ -12,11 +12,12 @@ module Network.HTTP.Lucu.Preprocess where import Control.Applicative import Control.Monad -import Control.Monad.State +import Control.Monad.State.Strict import Data.Ascii (Ascii) import qualified Data.Ascii as A import qualified Data.ByteString.Char8 as C8 import Data.Maybe +import qualified Data.Strict.Maybe as S import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Encoding as T @@ -30,12 +31,13 @@ import Prelude.Unicode data AugmentedRequest = AugmentedRequest { - arRequest ∷ !(Maybe Request) + arRequest ∷ !Request , arInitialStatus ∷ !StatusCode - , arWillClose ∷ !Bool + , arWillChunkBody ∷ !Bool , arWillDiscardBody ∷ !Bool - , arExpectedContinue ∷ !(Maybe Bool) - , arReqBodyLength ∷ !(Maybe RequestBodyLength) + , arWillClose ∷ !Bool + , arExpectedContinue ∷ !Bool + , arReqBodyLength ∷ !(S.Maybe RequestBodyLength) } data RequestBodyLength @@ -43,42 +45,20 @@ data RequestBodyLength | Chunked deriving (Eq, Show) -preprocess ∷ Text - → PortNumber - → Either StatusCode Request - → AugmentedRequest -preprocess localHost localPort request - = case request of - Right req - → preprocess' localHost localPort req - Left sc - → unparsable sc - -unparsable ∷ StatusCode → AugmentedRequest -unparsable sc - = AugmentedRequest { - arRequest = Nothing - , arInitialStatus = sc - , arWillClose = True - , arWillDiscardBody = False - , arExpectedContinue = Nothing - , arReqBodyLength = Nothing - } - -preprocess' ∷ Text → PortNumber → Request → AugmentedRequest -preprocess' localHost localPort req@(Request {..}) +preprocess ∷ Text → PortNumber → Request → AugmentedRequest +preprocess localHost localPort req@(Request {..}) = execState go initialAR where initialAR ∷ AugmentedRequest initialAR = AugmentedRequest { - arRequest = Just req + arRequest = req , arInitialStatus = Ok - , arWillClose = False + , arWillChunkBody = False , arWillDiscardBody = False - , arExpectedContinue = Just False - , arReqBodyLength = Nothing + , arWillClose = False + , arExpectedContinue = False + , arReqBodyLength = S.Nothing } - go ∷ State AugmentedRequest () go = do examineHttpVersion examineMethod @@ -88,7 +68,7 @@ preprocess' localHost localPort req@(Request {..}) setRequest ∷ Request → State AugmentedRequest () setRequest req - = modify $ \ar → ar { arRequest = Just req } + = modify $ \ar → ar { arRequest = req } setStatus ∷ StatusCode → State AugmentedRequest () setStatus sc @@ -98,25 +78,25 @@ setWillClose ∷ Bool → State AugmentedRequest () setWillClose b = modify $ \ar → ar { arWillClose = b } -setBodyLength ∷ Maybe RequestBodyLength → State AugmentedRequest () +setBodyLength ∷ S.Maybe RequestBodyLength → State AugmentedRequest () setBodyLength len = modify $ \ar → ar { arReqBodyLength = len } examineHttpVersion ∷ State AugmentedRequest () examineHttpVersion - = do req ← gets (fromJust ∘ arRequest) + = do req ← gets arRequest case reqVersion req of -- HTTP/1.0 requests can't Keep-Alive. HttpVersion 1 0 → setWillClose True HttpVersion 1 1 - → return () + → modify $ \ar → ar { arWillChunkBody = True } _ → do setStatus HttpVersionNotSupported setWillClose True examineMethod ∷ State AugmentedRequest () examineMethod - = do req ← gets (fromJust ∘ arRequest) + = do req ← gets arRequest case reqMethod req of GET → return () HEAD → modify $ \ar → ar { arWillDiscardBody = True } @@ -127,7 +107,7 @@ examineMethod examineAuthority ∷ Text → PortNumber → State AugmentedRequest () examineAuthority localHost localPort - = do req ← gets (fromJust ∘ arRequest) + = do req ← gets arRequest when (isNothing $ uriAuthority $ reqURI req) $ case reqVersion req of -- HTTP/1.0 requests have no Host header so complete it @@ -178,13 +158,13 @@ updateAuthority host port req examineHeaders ∷ State AugmentedRequest () examineHeaders - = do req ← gets (fromJust ∘ arRequest) + = do req ← gets arRequest case getCIHeader "Expect" req of Nothing → return () Just v | v ≡ "100-continue" - → modify $ \ar → ar { arExpectedContinue = Just True } + → modify $ \ar → ar { arExpectedContinue = True } | otherwise → setStatus ExpectationFailed @@ -194,7 +174,7 @@ examineHeaders | v ≡ "identity" → return () | v ≡ "chunked" - → setBodyLength $ Just Chunked + → setBodyLength $ S.Just Chunked | otherwise → setStatus NotImplemented @@ -203,7 +183,7 @@ examineHeaders Just value → case C8.readInt value of Just (len, garbage) | C8.null garbage ∧ len ≥ 0 - → setBodyLength $ Just $ Fixed len + → setBodyLength $ S.Just $ Fixed len _ → setStatus BadRequest case getCIHeader "Connection" req of @@ -214,13 +194,13 @@ examineHeaders examineBodyLength ∷ State AugmentedRequest () examineBodyLength - = do req ← gets (fromJust ∘ arRequest) + = do req ← gets arRequest len ← gets arReqBodyLength if reqMustHaveBody req then -- POST and PUT requests must have an entity body. - when (isNothing len) + when (S.isNothing len) $ setStatus LengthRequired else -- Other requests must NOT have an entity body. - when (isJust len) + when (S.isJust len) $ setStatus BadRequest