Make RandomGen parameter optional

This commit is contained in:
Michael Snoyman 2013-03-10 14:34:00 +02:00
parent 5b5203a275
commit 070e0aa8b3
3 changed files with 48 additions and 25 deletions

View File

@ -284,7 +284,11 @@ defaultYesodRunner YesodRunnerEnv {..} handler' req
let dontSaveSession _ = return [] let dontSaveSession _ = return []
(session, saveSession) <- liftIO $ do (session, saveSession) <- liftIO $ do
maybe (return (Map.empty, dontSaveSession)) (\sb -> sbLoadSession sb yreMaster req) yreSessionBackend maybe (return (Map.empty, dontSaveSession)) (\sb -> sbLoadSession sb yreMaster req) yreSessionBackend
yreq <- liftIO $ parseWaiRequest req session (isJust yreSessionBackend) maxLen <$> newStdGen let mkYesodReq = parseWaiRequest req session (isJust yreSessionBackend) maxLen
yreq <-
case mkYesodReq of
Left yreq -> return yreq
Right needGen -> liftIO $ needGen <$> newStdGen
let ra = resolveApproot yreMaster req let ra = resolveApproot yreMaster req
let log' = messageLoggerSource yreMaster yreLogger let log' = messageLoggerSource yreMaster yreLogger
-- We set up two environments: the first one has a "safe" error handler -- We set up two environments: the first one has a "safe" error handler

View File

@ -72,21 +72,27 @@ parseWaiRequest :: RandomGen g
-> SessionMap -> SessionMap
-> Bool -> Bool
-> Word64 -- ^ max body size -> Word64 -- ^ max body size
-> g -> (Either YesodRequest (g -> YesodRequest))
-> YesodRequest parseWaiRequest env session useToken maxBodySize =
parseWaiRequest env session useToken maxBodySize gen = -- In most cases, we won't need to generate any random values. Therefore,
YesodRequest -- we split our results: if we need a random generator, return a Right
-- value, otherwise return a Left and avoid the relatively costly generator
-- acquisition.
case etoken of
Left token -> Left $ mkRequest token
Right mkToken -> Right $ mkRequest . mkToken
where
mkRequest token' = YesodRequest
{ reqGetParams = gets { reqGetParams = gets
, reqCookies = cookies , reqCookies = cookies
, reqWaiRequest = limitRequestBody maxBodySize env , reqWaiRequest = limitRequestBody maxBodySize env
, reqLangs = langs'' , reqLangs = langs''
, reqToken = token , reqToken = token'
, reqSession = if useToken , reqSession = if useToken
then Map.delete tokenKey session then Map.delete tokenKey session
else session else session
, reqAccept = httpAccept env , reqAccept = httpAccept env
} }
where
gets = map (second $ fromMaybe "") gets = map (second $ fromMaybe "")
$ queryToQueryText $ queryToQueryText
$ W.queryString env $ W.queryString env
@ -111,12 +117,14 @@ parseWaiRequest env session useToken maxBodySize gen =
-- tokenKey present in the session is ignored). If sessions -- tokenKey present in the session is ignored). If sessions
-- are enabled and a session has no tokenKey a new one is -- are enabled and a session has no tokenKey a new one is
-- generated. -- generated.
token = if not useToken etoken
then Nothing | useToken =
else Just $ maybe case Map.lookup tokenKey session of
(pack $ randomString 10 gen) -- Already have a token, use it.
(decodeUtf8With lenientDecode) Just bs -> Left $ Just $ decodeUtf8With lenientDecode bs
(Map.lookup tokenKey session) -- Don't have a token, get a random generator and make a new one.
Nothing -> Right $ Just . pack . randomString 10
| otherwise = Left Nothing
-- | Get the list of accepted content types from the WAI Request\'s Accept -- | Get the list of accepted content types from the WAI Request\'s Accept
-- header. -- header.

View File

@ -11,6 +11,8 @@ import Yesod.Request (YesodRequest (..))
import Test.Hspec import Test.Hspec
import Data.Monoid (mempty) import Data.Monoid (mempty)
import Data.Map (singleton) import Data.Map (singleton)
import Yesod.Core (SessionMap)
import Data.Word (Word64)
randomStringSpecs :: Spec randomStringSpecs :: Spec
randomStringSpecs = describe "Yesod.Internal.Request.randomString" $ do randomStringSpecs = describe "Yesod.Internal.Request.randomString" $ do
@ -30,6 +32,15 @@ noRepeat len n = length (nub $ map (randomString len . mkStdGen) [1..n]) == n
g :: StdGen g :: StdGen
g = error "test/YesodCoreTest/InternalRequest.g" g = error "test/YesodCoreTest/InternalRequest.g"
parseWaiRequest' :: Request
-> SessionMap
-> Bool
-> Word64
-> YesodRequest
parseWaiRequest' a b c d =
case parseWaiRequest a b c d of
Left yreq -> yreq
Right needGen -> needGen g
tokenSpecs :: Spec tokenSpecs :: Spec
tokenSpecs = describe "Yesod.Internal.Request.parseWaiRequest (reqToken)" $ do tokenSpecs = describe "Yesod.Internal.Request.parseWaiRequest (reqToken)" $ do
@ -40,19 +51,19 @@ tokenSpecs = describe "Yesod.Internal.Request.parseWaiRequest (reqToken)" $ do
noDisabledToken :: Bool noDisabledToken :: Bool
noDisabledToken = reqToken r == Nothing where noDisabledToken = reqToken r == Nothing where
r = parseWaiRequest defaultRequest mempty False 1000 g r = parseWaiRequest' defaultRequest mempty False 1000
ignoreDisabledToken :: Bool ignoreDisabledToken :: Bool
ignoreDisabledToken = reqToken r == Nothing where ignoreDisabledToken = reqToken r == Nothing where
r = parseWaiRequest defaultRequest (singleton "_TOKEN" "old") False 1000 g r = parseWaiRequest' defaultRequest (singleton "_TOKEN" "old") False 1000
useOldToken :: Bool useOldToken :: Bool
useOldToken = reqToken r == Just "old" where useOldToken = reqToken r == Just "old" where
r = parseWaiRequest defaultRequest (singleton "_TOKEN" "old") True 1000 g r = parseWaiRequest' defaultRequest (singleton "_TOKEN" "old") True 1000
generateToken :: Bool generateToken :: Bool
generateToken = reqToken r /= Nothing where generateToken = reqToken r /= Nothing where
r = parseWaiRequest defaultRequest (singleton "_TOKEN" "old") True 1000 g r = parseWaiRequest' defaultRequest (singleton "_TOKEN" "old") True 1000
langSpecs :: Spec langSpecs :: Spec
@ -65,31 +76,31 @@ langSpecs = describe "Yesod.Internal.Request.parseWaiRequest (reqLangs)" $ do
respectAcceptLangs :: Bool respectAcceptLangs :: Bool
respectAcceptLangs = reqLangs r == ["en-US", "es", "en"] where respectAcceptLangs = reqLangs r == ["en-US", "es", "en"] where
r = parseWaiRequest defaultRequest r = parseWaiRequest' defaultRequest
{ requestHeaders = [("Accept-Language", "en-US, es")] } mempty False 1000 g { requestHeaders = [("Accept-Language", "en-US, es")] } mempty False 1000
respectSessionLang :: Bool respectSessionLang :: Bool
respectSessionLang = reqLangs r == ["en"] where respectSessionLang = reqLangs r == ["en"] where
r = parseWaiRequest defaultRequest (singleton "_LANG" "en") False 1000 g r = parseWaiRequest' defaultRequest (singleton "_LANG" "en") False 1000
respectCookieLang :: Bool respectCookieLang :: Bool
respectCookieLang = reqLangs r == ["en"] where respectCookieLang = reqLangs r == ["en"] where
r = parseWaiRequest defaultRequest r = parseWaiRequest' defaultRequest
{ requestHeaders = [("Cookie", "_LANG=en")] { requestHeaders = [("Cookie", "_LANG=en")]
} mempty False 1000 g } mempty False 1000
respectQueryLang :: Bool respectQueryLang :: Bool
respectQueryLang = reqLangs r == ["en-US", "en"] where respectQueryLang = reqLangs r == ["en-US", "en"] where
r = parseWaiRequest defaultRequest { queryString = [("_LANG", Just "en-US")] } mempty False 1000 g r = parseWaiRequest' defaultRequest { queryString = [("_LANG", Just "en-US")] } mempty False 1000
prioritizeLangs :: Bool prioritizeLangs :: Bool
prioritizeLangs = reqLangs r == ["en-QUERY", "en-COOKIE", "en-SESSION", "en", "es"] where prioritizeLangs = reqLangs r == ["en-QUERY", "en-COOKIE", "en-SESSION", "en", "es"] where
r = parseWaiRequest defaultRequest r = parseWaiRequest' defaultRequest
{ requestHeaders = [ ("Accept-Language", "en, es") { requestHeaders = [ ("Accept-Language", "en, es")
, ("Cookie", "_LANG=en-COOKIE") , ("Cookie", "_LANG=en-COOKIE")
] ]
, queryString = [("_LANG", Just "en-QUERY")] , queryString = [("_LANG", Just "en-QUERY")]
} (singleton "_LANG" "en-SESSION") False 10000 g } (singleton "_LANG" "en-SESSION") False 10000
internalRequestTest :: Spec internalRequestTest :: Spec
internalRequestTest = describe "Test.InternalRequestTest" $ do internalRequestTest = describe "Test.InternalRequestTest" $ do