Allow overriding status code in error handlers
This commit is contained in:
parent
97b78ad481
commit
d5b66d35d5
@ -32,7 +32,7 @@ yarToResponse :: Monad m
|
|||||||
-> YesodRequest
|
-> YesodRequest
|
||||||
-> m Response
|
-> m Response
|
||||||
yarToResponse (YRWai a) _ _ = return a
|
yarToResponse (YRWai a) _ _ = return a
|
||||||
yarToResponse (YRPlain s hs ct c newSess) saveSession yreq = do
|
yarToResponse (YRPlain s' hs ct c newSess) saveSession yreq = do
|
||||||
extraHeaders <- do
|
extraHeaders <- do
|
||||||
let nsToken = maybe
|
let nsToken = maybe
|
||||||
newSess
|
newSess
|
||||||
@ -50,6 +50,23 @@ yarToResponse (YRPlain s hs ct c newSess) saveSession yreq = do
|
|||||||
go (ContentSource body) = ResponseSource s finalHeaders body
|
go (ContentSource body) = ResponseSource s finalHeaders body
|
||||||
go (ContentDontEvaluate c') = go c'
|
go (ContentDontEvaluate c') = go c'
|
||||||
return $ go c
|
return $ go c
|
||||||
|
where
|
||||||
|
s
|
||||||
|
| s' == defaultStatus = H.status200
|
||||||
|
| otherwise = s'
|
||||||
|
|
||||||
|
-- | Indicates that the user provided no specific status code to be used, and
|
||||||
|
-- therefore the default status code should be used. For normal responses, this
|
||||||
|
-- would be a 200 response, whereas for error responses this would be an
|
||||||
|
-- appropriate status code.
|
||||||
|
--
|
||||||
|
-- For more information on motivation for this, see:
|
||||||
|
--
|
||||||
|
-- https://groups.google.com/d/msg/yesodweb/vHDBzyu28TM/bezCvviWp4sJ
|
||||||
|
--
|
||||||
|
-- Since 1.2.3.1
|
||||||
|
defaultStatus :: H.Status
|
||||||
|
defaultStatus = H.mkStatus (-1) "INVALID DEFAULT STATUS"
|
||||||
|
|
||||||
-- | Convert Header to a key/value pair.
|
-- | Convert Header to a key/value pair.
|
||||||
headerToPair :: Header
|
headerToPair :: Header
|
||||||
|
|||||||
@ -73,15 +73,18 @@ runHandler rhe@RunHandlerEnv {..} handler yreq = withInternalState $ \resState -
|
|||||||
state <- liftIO $ I.readIORef istate
|
state <- liftIO $ I.readIORef istate
|
||||||
let finalSession = ghsSession state
|
let finalSession = ghsSession state
|
||||||
let headers = ghsHeaders state
|
let headers = ghsHeaders state
|
||||||
let contents = either id (HCContent H.status200 . toTypedContent) contents'
|
let contents = 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 _ hs ct c sess ->
|
YRPlain status' hs ct c sess ->
|
||||||
let hs' = appEndo headers hs
|
let hs' = appEndo headers hs
|
||||||
in return $ YRPlain (getStatus e) hs' ct c sess
|
status
|
||||||
|
| status' == defaultStatus = getStatus e
|
||||||
|
| otherwise = status'
|
||||||
|
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 (appEndo headers []) ct (ContentFile fp p) finalSession
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import Text.Hamlet (hamlet)
|
|||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
import qualified Data.ByteString.Char8 as S8
|
import qualified Data.ByteString.Char8 as S8
|
||||||
import Control.Exception (SomeException, try)
|
import Control.Exception (SomeException, try)
|
||||||
|
import Network.HTTP.Types (mkStatus)
|
||||||
|
|
||||||
data App = App
|
data App = App
|
||||||
|
|
||||||
@ -22,9 +23,14 @@ mkYesod "App" [parseRoutes|
|
|||||||
/after_runRequestBody AfterRunRequestBodyR POST
|
/after_runRequestBody AfterRunRequestBodyR POST
|
||||||
/error-in-body ErrorInBodyR GET
|
/error-in-body ErrorInBodyR GET
|
||||||
/error-in-body-noeval ErrorInBodyNoEvalR GET
|
/error-in-body-noeval ErrorInBodyNoEvalR GET
|
||||||
|
/override-status OverrideStatusR GET
|
||||||
|]
|
|]
|
||||||
|
|
||||||
instance Yesod App
|
overrideStatus = mkStatus 15 "OVERRIDE"
|
||||||
|
|
||||||
|
instance Yesod App where
|
||||||
|
errorHandler (InvalidArgs ["OVERRIDE"]) = sendResponseStatus overrideStatus ("OH HAI" :: String)
|
||||||
|
errorHandler x = defaultErrorHandler x
|
||||||
|
|
||||||
getHomeR :: Handler Html
|
getHomeR :: Handler Html
|
||||||
getHomeR = do
|
getHomeR = do
|
||||||
@ -65,6 +71,9 @@ getErrorInBodyR = do
|
|||||||
getErrorInBodyNoEvalR :: Handler (DontFullyEvaluate Html)
|
getErrorInBodyNoEvalR :: Handler (DontFullyEvaluate Html)
|
||||||
getErrorInBodyNoEvalR = fmap DontFullyEvaluate getErrorInBodyR
|
getErrorInBodyNoEvalR = fmap DontFullyEvaluate getErrorInBodyR
|
||||||
|
|
||||||
|
getOverrideStatusR :: Handler ()
|
||||||
|
getOverrideStatusR = invalidArgs ["OVERRIDE"]
|
||||||
|
|
||||||
errorHandlingTest :: Spec
|
errorHandlingTest :: Spec
|
||||||
errorHandlingTest = describe "Test.ErrorHandling" $ do
|
errorHandlingTest = describe "Test.ErrorHandling" $ do
|
||||||
it "says not found" caseNotFound
|
it "says not found" caseNotFound
|
||||||
@ -72,6 +81,7 @@ errorHandlingTest = describe "Test.ErrorHandling" $ do
|
|||||||
it "says 'There was an error' after runRequestBody" caseAfter
|
it "says 'There was an error' after runRequestBody" caseAfter
|
||||||
it "error in body == 500" caseErrorInBody
|
it "error in body == 500" caseErrorInBody
|
||||||
it "error in body, no eval == 200" caseErrorInBodyNoEval
|
it "error in body, no eval == 200" caseErrorInBodyNoEval
|
||||||
|
it "can override status code" caseOverrideStatus
|
||||||
|
|
||||||
runner :: Session () -> IO ()
|
runner :: Session () -> IO ()
|
||||||
runner f = toWaiApp App >>= runSession f
|
runner f = toWaiApp App >>= runSession f
|
||||||
@ -125,3 +135,8 @@ caseErrorInBodyNoEval = do
|
|||||||
case eres of
|
case eres of
|
||||||
Left (_ :: SomeException) -> return ()
|
Left (_ :: SomeException) -> return ()
|
||||||
Right _ -> error "Expected an exception"
|
Right _ -> error "Expected an exception"
|
||||||
|
|
||||||
|
caseOverrideStatus :: IO ()
|
||||||
|
caseOverrideStatus = runner $ do
|
||||||
|
res <- request defaultRequest { pathInfo = ["override-status"] }
|
||||||
|
assertStatus 15 res
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-core
|
name: yesod-core
|
||||||
version: 1.2.3
|
version: 1.2.3.1
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user