Full support for ResponseEnumerator
This commit is contained in:
parent
68e5969ecf
commit
b2e95911d8
@ -313,30 +313,33 @@ toWaiApp' y key' segments env = do
|
|||||||
let ya = runHandler h render eurl' id y id
|
let ya = runHandler h render eurl' id y id
|
||||||
let sessionMap = Map.fromList
|
let sessionMap = Map.fromList
|
||||||
$ filter (\(x, _) -> x /= nonceKey) session'
|
$ filter (\(x, _) -> x /= nonceKey) session'
|
||||||
(s, hs, ct, c, sessionFinal) <- unYesodApp ya eh rr types sessionMap
|
yar <- unYesodApp ya eh rr types sessionMap
|
||||||
let sessionVal =
|
case yar of
|
||||||
case key' of
|
YARPlain s hs ct c sessionFinal -> do
|
||||||
Nothing -> B.empty
|
let sessionVal =
|
||||||
Just key'' ->
|
case key' of
|
||||||
encodeSession key'' exp' host
|
Nothing -> B.empty
|
||||||
$ Map.toList
|
Just key'' ->
|
||||||
$ Map.insert nonceKey (reqNonce rr) sessionFinal
|
encodeSession key'' exp' host
|
||||||
let hs' =
|
$ Map.toList
|
||||||
case key' of
|
$ Map.insert nonceKey (reqNonce rr) sessionFinal
|
||||||
Nothing -> hs
|
let hs' =
|
||||||
Just _ -> AddCookie
|
case key' of
|
||||||
(clientSessionDuration y)
|
Nothing -> hs
|
||||||
sessionName
|
Just _ -> AddCookie
|
||||||
(bsToChars sessionVal)
|
(clientSessionDuration y)
|
||||||
: hs
|
sessionName
|
||||||
hs'' = map (headerToPair getExpires) hs'
|
(bsToChars sessionVal)
|
||||||
hs''' = ("Content-Type", charsToBs ct) : hs''
|
: hs
|
||||||
return $
|
hs'' = map (headerToPair getExpires) hs'
|
||||||
case c of
|
hs''' = ("Content-Type", charsToBs ct) : hs''
|
||||||
ContentLBS lbs -> W.ResponseLBS s hs''' lbs
|
return $
|
||||||
ContentFile fp -> W.ResponseFile s hs''' fp
|
case c of
|
||||||
ContentEnum e -> W.ResponseEnumerator $ \iter ->
|
ContentLBS lbs -> W.ResponseLBS s hs''' lbs
|
||||||
run_ $ e $$ iter s hs'''
|
ContentFile fp -> W.ResponseFile s hs''' fp
|
||||||
|
ContentEnum e -> W.ResponseEnumerator $ \iter ->
|
||||||
|
run_ $ e $$ iter s hs'''
|
||||||
|
YAREnum e -> return $ W.ResponseEnumerator e
|
||||||
|
|
||||||
httpAccept :: W.Request -> [ContentType]
|
httpAccept :: W.Request -> [ContentType]
|
||||||
httpAccept = map B.unpack
|
httpAccept = map B.unpack
|
||||||
|
|||||||
@ -51,6 +51,7 @@ module Yesod.Handler
|
|||||||
, sendResponse
|
, sendResponse
|
||||||
, sendResponseStatus
|
, sendResponseStatus
|
||||||
, sendResponseCreated
|
, sendResponseCreated
|
||||||
|
, sendResponseEnumerator
|
||||||
-- * Setting headers
|
-- * Setting headers
|
||||||
, setCookie
|
, setCookie
|
||||||
, deleteCookie
|
, deleteCookie
|
||||||
@ -85,6 +86,7 @@ module Yesod.Handler
|
|||||||
, localNoCurrent
|
, localNoCurrent
|
||||||
, HandlerData
|
, HandlerData
|
||||||
, ErrorResponse (..)
|
, ErrorResponse (..)
|
||||||
|
, YesodAppResult (..)
|
||||||
#if TEST
|
#if TEST
|
||||||
, testSuite
|
, testSuite
|
||||||
#endif
|
#endif
|
||||||
@ -232,15 +234,20 @@ newtype YesodApp = YesodApp
|
|||||||
-> Request
|
-> Request
|
||||||
-> [ContentType]
|
-> [ContentType]
|
||||||
-> SessionMap
|
-> SessionMap
|
||||||
-> IO (W.Status, [Header], ContentType, Content, SessionMap)
|
-> IO YesodAppResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data YesodAppResult
|
||||||
|
= YAREnum (forall a. W.ResponseEnumerator a)
|
||||||
|
| YARPlain W.Status [Header] ContentType Content SessionMap
|
||||||
|
|
||||||
data HandlerContents =
|
data HandlerContents =
|
||||||
HCContent W.Status ChooseRep
|
HCContent W.Status ChooseRep
|
||||||
| HCError ErrorResponse
|
| HCError ErrorResponse
|
||||||
| HCSendFile ContentType FilePath
|
| HCSendFile ContentType FilePath
|
||||||
| HCRedirect RedirectType String
|
| HCRedirect RedirectType String
|
||||||
| HCCreated String
|
| HCCreated String
|
||||||
|
| HCEnum (forall a. W.ResponseEnumerator a)
|
||||||
|
|
||||||
instance Failure ErrorResponse (GHandler sub master) where
|
instance Failure ErrorResponse (GHandler sub master) where
|
||||||
failure = GHandler . lift . throwMEither . HCError
|
failure = GHandler . lift . throwMEither . HCError
|
||||||
@ -307,34 +314,46 @@ runHandler handler mrender sroute tomr ma tosa =
|
|||||||
) (\e -> return ((MLeft $ HCError $ toErrorHandler e, id), initSession))
|
) (\e -> return ((MLeft $ HCError $ toErrorHandler e, id), initSession))
|
||||||
let contents = meither id (HCContent W.status200 . chooseRep) contents'
|
let contents = meither id (HCContent W.status200 . chooseRep) contents'
|
||||||
let handleError e = do
|
let handleError e = do
|
||||||
(_, hs, ct, c, sess) <- unYesodApp (eh e) safeEh rr cts finalSession
|
yar <- unYesodApp (eh e) safeEh rr cts finalSession
|
||||||
let hs' = headers hs
|
case yar of
|
||||||
return (getStatus e, hs', ct, c, sess)
|
YARPlain _ hs ct c sess ->
|
||||||
|
let hs' = headers hs
|
||||||
|
in return $ YARPlain (getStatus e) hs' ct c sess
|
||||||
|
YAREnum _ -> return yar
|
||||||
let sendFile' ct fp =
|
let sendFile' ct fp =
|
||||||
return (W.status200, headers [], ct, ContentFile fp, finalSession)
|
return $ YARPlain W.status200 (headers []) ct (ContentFile fp) finalSession
|
||||||
case contents of
|
case contents of
|
||||||
HCContent status a -> do
|
HCContent status a -> do
|
||||||
(ct, c) <- chooseRep a cts
|
(ct, c) <- chooseRep a cts
|
||||||
return (status, headers [], ct, c, finalSession)
|
return $ YARPlain status (headers []) ct c finalSession
|
||||||
HCError e -> handleError e
|
HCError e -> handleError e
|
||||||
HCRedirect rt loc -> do
|
HCRedirect rt loc -> do
|
||||||
let hs = Header "Location" loc : headers []
|
let hs = Header "Location" loc : headers []
|
||||||
return (getRedirectStatus rt, hs, typePlain, emptyContent,
|
return $ YARPlain
|
||||||
finalSession)
|
(getRedirectStatus rt) hs typePlain emptyContent
|
||||||
|
finalSession
|
||||||
HCSendFile ct fp -> E.catch
|
HCSendFile ct fp -> E.catch
|
||||||
(sendFile' ct fp)
|
(sendFile' ct fp)
|
||||||
(handleError . toErrorHandler)
|
(handleError . toErrorHandler)
|
||||||
HCCreated loc -> do
|
HCCreated loc -> do -- FIXME add status201 to WAI
|
||||||
let hs = Header "Location" loc : headers []
|
let hs = Header "Location" loc : headers []
|
||||||
return (W.Status 201 (S8.pack "Created"), hs, typePlain,
|
return $ YARPlain
|
||||||
emptyContent,
|
(W.Status 201 (S8.pack "Created"))
|
||||||
finalSession)
|
hs
|
||||||
|
typePlain
|
||||||
|
emptyContent
|
||||||
|
finalSession
|
||||||
|
HCEnum e -> return $ YAREnum e
|
||||||
|
|
||||||
safeEh :: ErrorResponse -> YesodApp
|
safeEh :: ErrorResponse -> YesodApp
|
||||||
safeEh er = YesodApp $ \_ _ _ session -> do
|
safeEh er = YesodApp $ \_ _ _ session -> do
|
||||||
liftIO $ hPutStrLn stderr $ "Error handler errored out: " ++ show er
|
liftIO $ hPutStrLn stderr $ "Error handler errored out: " ++ show er
|
||||||
return (W.status500, [], typePlain, toContent "Internal Server Error",
|
return $ YARPlain
|
||||||
session)
|
W.status500
|
||||||
|
[]
|
||||||
|
typePlain
|
||||||
|
(toContent "Internal Server Error")
|
||||||
|
session
|
||||||
|
|
||||||
-- | Redirect to the given route.
|
-- | Redirect to the given route.
|
||||||
redirect :: RedirectType -> Route master -> GHandler sub master a
|
redirect :: RedirectType -> Route master -> GHandler sub master a
|
||||||
@ -439,6 +458,14 @@ sendResponseCreated url = do
|
|||||||
r <- getUrlRender
|
r <- getUrlRender
|
||||||
GHandler $ lift $ throwMEither $ HCCreated $ r url
|
GHandler $ lift $ throwMEither $ HCCreated $ r url
|
||||||
|
|
||||||
|
-- | Send a 'W.ResponseEnumerator'. Please note: this function is rarely
|
||||||
|
-- necessary, and will /disregard/ any changes to response headers and session
|
||||||
|
-- that you have already specified. This function short-circuits. It should be
|
||||||
|
-- considered only for they specific needs. If you are not sure if you need it,
|
||||||
|
-- you don't.
|
||||||
|
sendResponseEnumerator :: (forall a. W.ResponseEnumerator a) -> GHandler s m b
|
||||||
|
sendResponseEnumerator = GHandler . lift . throwMEither . HCEnum
|
||||||
|
|
||||||
-- | Return a 404 not found page. Also denotes no handler available.
|
-- | Return a 404 not found page. Also denotes no handler available.
|
||||||
notFound :: Failure ErrorResponse m => m a
|
notFound :: Failure ErrorResponse m => m a
|
||||||
notFound = failure NotFound
|
notFound = failure NotFound
|
||||||
@ -559,6 +586,3 @@ testSuite = testGroup "Yesod.Handler"
|
|||||||
]
|
]
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
-- FIXME add a sendEnum that uses a ResponseEnumerator and bypasses all status
|
|
||||||
-- and header stuff
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user