Only read request body when needed
This commit is contained in:
parent
89f40e48d0
commit
a95704d164
@ -53,7 +53,8 @@ runFormGeneric params (Form f) =
|
|||||||
runFormPost :: Form x -> Handler y x
|
runFormPost :: Form x -> Handler y x
|
||||||
runFormPost f = do
|
runFormPost f = do
|
||||||
rr <- getRawRequest
|
rr <- getRawRequest
|
||||||
runFormGeneric (postParams rr) f
|
pp <- postParams rr
|
||||||
|
runFormGeneric pp f
|
||||||
|
|
||||||
-- | Run a form against GET parameters.
|
-- | Run a form against GET parameters.
|
||||||
runFormGet :: Form x -> Handler y x
|
runFormGet :: Form x -> Handler y x
|
||||||
|
|||||||
@ -170,10 +170,11 @@ rpxnowLogin = do
|
|||||||
Just x -> return x
|
Just x -> return x
|
||||||
Nothing -> notFound
|
Nothing -> notFound
|
||||||
rr <- getRawRequest
|
rr <- getRawRequest
|
||||||
let token = case getParams rr "token" ++ postParams rr "token" of
|
pp <- postParams rr
|
||||||
|
let token = case getParams rr "token" ++ pp "token" of
|
||||||
[] -> failure MissingToken
|
[] -> failure MissingToken
|
||||||
(x:_) -> x
|
(x:_) -> x
|
||||||
let dest = case postParams rr "dest" of
|
let dest = case pp "dest" of
|
||||||
[] -> case getParams rr "dest" of
|
[] -> case getParams rr "dest" of
|
||||||
[] -> ar
|
[] -> ar
|
||||||
("":_) -> ar
|
("":_) -> ar
|
||||||
|
|||||||
@ -48,6 +48,8 @@ import Data.Convertible.Text
|
|||||||
import Control.Arrow ((***))
|
import Control.Arrow ((***))
|
||||||
import Control.Exception (SomeException (..))
|
import Control.Exception (SomeException (..))
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Control.Monad.Trans
|
||||||
|
import Control.Concurrent.MVar
|
||||||
|
|
||||||
#if TEST
|
#if TEST
|
||||||
import Test.Framework (testGroup, Test)
|
import Test.Framework (testGroup, Test)
|
||||||
@ -71,32 +73,36 @@ languages = rawLangs `fmap` getRawRequest
|
|||||||
parseEnv :: (Functor m, RequestReader m) => m W.Request
|
parseEnv :: (Functor m, RequestReader m) => m W.Request
|
||||||
parseEnv = rawRequest `fmap` getRawRequest
|
parseEnv = rawRequest `fmap` getRawRequest
|
||||||
|
|
||||||
|
type RequestBodyContents =
|
||||||
|
( [(ParamName, ParamValue)]
|
||||||
|
, [(ParamName, FileInfo String BL.ByteString)]
|
||||||
|
)
|
||||||
|
|
||||||
-- | The raw information passed through W, cleaned up a bit.
|
-- | The raw information passed through W, cleaned up a bit.
|
||||||
data RawRequest = RawRequest
|
data RawRequest = RawRequest
|
||||||
{ rawGetParams :: [(ParamName, ParamValue)]
|
{ rawGetParams :: [(ParamName, ParamValue)]
|
||||||
, rawCookies :: [(ParamName, ParamValue)]
|
, rawCookies :: [(ParamName, ParamValue)]
|
||||||
, rawSession :: [(B.ByteString, B.ByteString)]
|
, rawSession :: [(B.ByteString, B.ByteString)]
|
||||||
-- when we switch to WAI, the following two should be combined and
|
, rawRequestBody :: IO RequestBodyContents
|
||||||
-- wrapped in the IO monad
|
|
||||||
, rawPostParams :: [(ParamName, ParamValue)]
|
|
||||||
, rawFiles :: [(ParamName, FileInfo String BL.ByteString)]
|
|
||||||
, rawRequest :: W.Request
|
, rawRequest :: W.Request
|
||||||
, rawLangs :: [Language]
|
, rawLangs :: [Language]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multiLookup :: [(ParamName, ParamValue)] -> ParamName -> [ParamValue]
|
||||||
|
multiLookup [] _ = []
|
||||||
|
multiLookup ((k, v):rest) pn
|
||||||
|
| k == pn = v : multiLookup rest pn
|
||||||
|
| otherwise = multiLookup rest pn
|
||||||
|
|
||||||
-- | All GET paramater values with the given name.
|
-- | All GET paramater values with the given name.
|
||||||
getParams :: RawRequest -> ParamName -> [ParamValue]
|
getParams :: RawRequest -> ParamName -> [ParamValue]
|
||||||
getParams rr name = map snd
|
getParams rr = multiLookup $ rawGetParams rr
|
||||||
. filter (\x -> name == fst x)
|
|
||||||
. rawGetParams
|
|
||||||
$ rr
|
|
||||||
|
|
||||||
-- | All POST paramater values with the given name.
|
-- | All POST paramater values with the given name.
|
||||||
postParams :: RawRequest -> ParamName -> [ParamValue]
|
postParams :: MonadIO m => RawRequest -> m (ParamName -> [ParamValue])
|
||||||
postParams rr name = map snd
|
postParams rr = do
|
||||||
. filter (\x -> name == fst x)
|
(pp, _) <- liftIO $ rawRequestBody rr
|
||||||
. rawPostParams
|
return $ multiLookup pp
|
||||||
$ rr
|
|
||||||
|
|
||||||
-- | All cookies with the given name.
|
-- | All cookies with the given name.
|
||||||
cookies :: RawRequest -> ParamName -> [ParamValue]
|
cookies :: RawRequest -> ParamName -> [ParamValue]
|
||||||
@ -105,16 +111,7 @@ cookies rr name = map snd . filter (fst `equals` name) . rawCookies $ rr
|
|||||||
parseWaiRequest :: W.Request -> [(B.ByteString, B.ByteString)] -> IO RawRequest
|
parseWaiRequest :: W.Request -> [(B.ByteString, B.ByteString)] -> IO RawRequest
|
||||||
parseWaiRequest env session = do
|
parseWaiRequest env session = do
|
||||||
let gets' = map (cs *** cs) $ decodeUrlPairs $ W.queryString env
|
let gets' = map (cs *** cs) $ decodeUrlPairs $ W.queryString env
|
||||||
let clength = maybe "0" cs $ lookup W.ReqContentLength
|
let rawCookie = fromMaybe B.empty $ lookup W.Cookie $ W.httpHeaders env
|
||||||
$ W.httpHeaders env
|
|
||||||
let ctype = maybe "" cs $ lookup W.ReqContentType $ W.httpHeaders env
|
|
||||||
let convertFileInfo (FileInfo a b c) = FileInfo (cs a) (cs b) c
|
|
||||||
inputLBS <- WE.toLBS $ W.requestBody env -- FIXME
|
|
||||||
let (posts, files) = map (convertSuccess *** convertSuccess) ***
|
|
||||||
map (convertSuccess *** convertFileInfo)
|
|
||||||
$ parsePost ctype clength
|
|
||||||
inputLBS
|
|
||||||
rawCookie = fromMaybe B.empty $ lookup W.Cookie $ W.httpHeaders env
|
|
||||||
cookies' = map (cs *** cs) $ parseCookies rawCookie
|
cookies' = map (cs *** cs) $ parseCookies rawCookie
|
||||||
acceptLang = lookup W.AcceptLanguage $ W.httpHeaders env
|
acceptLang = lookup W.AcceptLanguage $ W.httpHeaders env
|
||||||
langs = map cs $ maybe [] parseHttpAccept acceptLang
|
langs = map cs $ maybe [] parseHttpAccept acceptLang
|
||||||
@ -124,7 +121,23 @@ parseWaiRequest env session = do
|
|||||||
langs'' = case lookup langKey gets' of
|
langs'' = case lookup langKey gets' of
|
||||||
Nothing -> langs'
|
Nothing -> langs'
|
||||||
Just x -> x : langs'
|
Just x -> x : langs'
|
||||||
return $ RawRequest gets' cookies' session posts files env langs''
|
mrb <- newMVar $ Left env
|
||||||
|
return $ RawRequest gets' cookies' session (rbHelper mrb) env langs''
|
||||||
|
|
||||||
|
rbHelper :: MVar (Either W.Request RequestBodyContents)
|
||||||
|
-> IO RequestBodyContents
|
||||||
|
rbHelper mvar = modifyMVar mvar helper where
|
||||||
|
helper (Right bc) = return (Right bc, bc)
|
||||||
|
helper (Left env) = do
|
||||||
|
inputLBS <- WE.toLBS $ W.requestBody env -- FIXME
|
||||||
|
let clength = maybe "0" cs $ lookup W.ReqContentLength
|
||||||
|
$ W.httpHeaders env
|
||||||
|
let ctype = maybe "" cs $ lookup W.ReqContentType $ W.httpHeaders env
|
||||||
|
let convertFileInfo (FileInfo a b c) = FileInfo (cs a) (cs b) c
|
||||||
|
let ret = map (cs *** cs) ***
|
||||||
|
map (cs *** convertFileInfo)
|
||||||
|
$ parsePost ctype clength inputLBS
|
||||||
|
return (Right ret, ret)
|
||||||
|
|
||||||
#if TEST
|
#if TEST
|
||||||
testSuite :: Test
|
testSuite :: Test
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user