Deeply evaluate session and headers #712
This commit is contained in:
parent
c44a48c8ae
commit
4dc7a1258c
@ -48,6 +48,7 @@ import Yesod.Core.Types
|
|||||||
import Yesod.Core.Internal.Request (parseWaiRequest,
|
import Yesod.Core.Internal.Request (parseWaiRequest,
|
||||||
tooLargeResponse)
|
tooLargeResponse)
|
||||||
import Yesod.Routes.Class (Route, renderRoute)
|
import Yesod.Routes.Class (Route, renderRoute)
|
||||||
|
import Control.DeepSeq (($!!))
|
||||||
|
|
||||||
-- | Function used internally by Yesod in the process of converting a
|
-- | Function used internally by Yesod in the process of converting a
|
||||||
-- 'HandlerT' into an 'Application'. Should not be needed by users.
|
-- 'HandlerT' into an 'Application'. Should not be needed by users.
|
||||||
@ -78,23 +79,38 @@ runHandler rhe@RunHandlerEnv {..} handler yreq = withInternalState $ \resState -
|
|||||||
(\e -> return $ Left $ maybe (HCError $ toErrorHandler e) id
|
(\e -> return $ Left $ maybe (HCError $ toErrorHandler e) id
|
||||||
$ fromException e)
|
$ fromException e)
|
||||||
state <- liftIO $ I.readIORef istate
|
state <- liftIO $ I.readIORef istate
|
||||||
let finalSession = ghsSession state
|
|
||||||
let headers = ghsHeaders state
|
(finalSession, mcontents1) <- (do
|
||||||
let contents = either id (HCContent defaultStatus . toTypedContent) contents'
|
finalSession <- return $!! ghsSession state
|
||||||
|
return (finalSession, Nothing)) `E.catch` \e -> return
|
||||||
|
(Map.empty, Just $! HCError $! InternalError $! T.pack $! show (e :: E.SomeException))
|
||||||
|
|
||||||
|
(headers, mcontents2) <- (do
|
||||||
|
headers <- return $!! appEndo (ghsHeaders state) []
|
||||||
|
return (headers, Nothing)) `E.catch` \e -> return
|
||||||
|
([], Just $! HCError $! InternalError $! T.pack $! show (e :: E.SomeException))
|
||||||
|
|
||||||
|
let contents =
|
||||||
|
case mcontents1 of
|
||||||
|
Just x -> x
|
||||||
|
Nothing ->
|
||||||
|
case mcontents2 of
|
||||||
|
Just x -> x
|
||||||
|
Nothing -> either id (HCContent defaultStatus . toTypedContent) contents'
|
||||||
let handleError e = flip runInternalState resState $ do
|
let handleError e = flip runInternalState resState $ do
|
||||||
yar <- rheOnError e yreq
|
yar <- rheOnError e yreq
|
||||||
{ reqSession = finalSession
|
{ reqSession = finalSession
|
||||||
}
|
}
|
||||||
case yar of
|
case yar of
|
||||||
YRPlain status' hs ct c sess ->
|
YRPlain status' hs ct c sess ->
|
||||||
let hs' = appEndo headers hs
|
let hs' = headers ++ hs
|
||||||
status
|
status
|
||||||
| status' == defaultStatus = getStatus e
|
| status' == defaultStatus = getStatus e
|
||||||
| otherwise = status'
|
| otherwise = status'
|
||||||
in return $ YRPlain status hs' ct c sess
|
in return $ YRPlain status hs' ct c sess
|
||||||
YRWai _ -> return yar
|
YRWai _ -> return yar
|
||||||
let sendFile' ct fp p =
|
let sendFile' ct fp p =
|
||||||
return $ YRPlain H.status200 (appEndo headers []) ct (ContentFile fp p) finalSession
|
return $ YRPlain H.status200 headers ct (ContentFile fp p) finalSession
|
||||||
contents1 <- evaluate contents `E.catch` \e -> return
|
contents1 <- evaluate contents `E.catch` \e -> return
|
||||||
(HCError $! InternalError $! T.pack $! show (e :: E.SomeException))
|
(HCError $! InternalError $! T.pack $! show (e :: E.SomeException))
|
||||||
case contents1 of
|
case contents1 of
|
||||||
@ -102,7 +118,7 @@ runHandler rhe@RunHandlerEnv {..} handler yreq = withInternalState $ \resState -
|
|||||||
ec' <- liftIO $ evaluateContent c
|
ec' <- liftIO $ evaluateContent c
|
||||||
case ec' of
|
case ec' of
|
||||||
Left e -> handleError e
|
Left e -> handleError e
|
||||||
Right c' -> return $ YRPlain status (appEndo headers []) ct c' finalSession
|
Right c' -> return $ YRPlain status headers ct c' finalSession
|
||||||
HCError e -> handleError e
|
HCError e -> handleError e
|
||||||
HCRedirect status loc -> do
|
HCRedirect status loc -> do
|
||||||
let disable_caching x =
|
let disable_caching x =
|
||||||
@ -110,7 +126,7 @@ runHandler rhe@RunHandlerEnv {..} handler yreq = withInternalState $ \resState -
|
|||||||
: Header "Expires" "Thu, 01 Jan 1970 05:05:05 GMT"
|
: Header "Expires" "Thu, 01 Jan 1970 05:05:05 GMT"
|
||||||
: x
|
: x
|
||||||
hs = (if status /= H.movedPermanently301 then disable_caching else id)
|
hs = (if status /= H.movedPermanently301 then disable_caching else id)
|
||||||
$ Header "Location" (encodeUtf8 loc) : appEndo headers []
|
$ Header "Location" (encodeUtf8 loc) : headers
|
||||||
return $ YRPlain
|
return $ YRPlain
|
||||||
status hs typePlain emptyContent
|
status hs typePlain emptyContent
|
||||||
finalSession
|
finalSession
|
||||||
@ -118,7 +134,7 @@ runHandler rhe@RunHandlerEnv {..} handler yreq = withInternalState $ \resState -
|
|||||||
(sendFile' ct fp p)
|
(sendFile' ct fp p)
|
||||||
(handleError . toErrorHandler)
|
(handleError . toErrorHandler)
|
||||||
HCCreated loc -> do
|
HCCreated loc -> do
|
||||||
let hs = Header "Location" (encodeUtf8 loc) : appEndo headers []
|
let hs = Header "Location" (encodeUtf8 loc) : headers
|
||||||
return $ YRPlain
|
return $ YRPlain
|
||||||
H.status201
|
H.status201
|
||||||
hs
|
hs
|
||||||
|
|||||||
@ -64,6 +64,7 @@ import Control.Monad.Trans.Class (MonadTrans (..))
|
|||||||
import Yesod.Routes.Class (RenderRoute (..), ParseRoute (..))
|
import Yesod.Routes.Class (RenderRoute (..), ParseRoute (..))
|
||||||
import Control.Monad.Reader (MonadReader (..))
|
import Control.Monad.Reader (MonadReader (..))
|
||||||
import Prelude hiding (catch)
|
import Prelude hiding (catch)
|
||||||
|
import Control.DeepSeq (NFData (rnf))
|
||||||
|
|
||||||
-- Sessions
|
-- Sessions
|
||||||
type SessionMap = Map Text ByteString
|
type SessionMap = Map Text ByteString
|
||||||
@ -312,6 +313,11 @@ data Header =
|
|||||||
| Header ByteString ByteString
|
| Header ByteString ByteString
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
instance NFData Header where
|
||||||
|
rnf (AddCookie x) = rnf x
|
||||||
|
rnf (DeleteCookie x y) = rnf x `seq` rnf y
|
||||||
|
rnf (Header x y) = rnf x `seq` rnf y
|
||||||
|
|
||||||
data Location url = Local url | Remote Text
|
data Location url = Local url | Remote Text
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ library
|
|||||||
, containers >= 0.2
|
, containers >= 0.2
|
||||||
, monad-control >= 0.3 && < 0.4
|
, monad-control >= 0.3 && < 0.4
|
||||||
, transformers-base >= 0.4
|
, transformers-base >= 0.4
|
||||||
, cookie >= 0.4 && < 0.5
|
, cookie >= 0.4.1 && < 0.5
|
||||||
, http-types >= 0.7
|
, http-types >= 0.7
|
||||||
, case-insensitive >= 0.2
|
, case-insensitive >= 0.2
|
||||||
, parsec >= 2 && < 3.2
|
, parsec >= 2 && < 3.2
|
||||||
@ -69,6 +69,7 @@ library
|
|||||||
, unix-compat
|
, unix-compat
|
||||||
, conduit-extra
|
, conduit-extra
|
||||||
, exceptions
|
, exceptions
|
||||||
|
, deepseq
|
||||||
|
|
||||||
exposed-modules: Yesod.Core
|
exposed-modules: Yesod.Core
|
||||||
Yesod.Core.Content
|
Yesod.Core.Content
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user