Added Yesod parameter to Handler
This commit is contained in:
parent
4650cf4e92
commit
ac54b644bc
@ -102,7 +102,7 @@ takeJusts (Just x:rest) = x : takeJusts rest
|
|||||||
|
|
||||||
toHackApplication :: RestfulApp resourceName
|
toHackApplication :: RestfulApp resourceName
|
||||||
=> resourceName
|
=> resourceName
|
||||||
-> (resourceName -> Verb -> Handler [(ContentType, Content)])
|
-> (resourceName -> Verb -> Handler resourceName [(ContentType, Content)])
|
||||||
-> Hack.Application
|
-> Hack.Application
|
||||||
toHackApplication sampleRN hm env = do
|
toHackApplication sampleRN hm env = do
|
||||||
-- The following is safe since we run cleanPath as middleware
|
-- The following is safe since we run cleanPath as middleware
|
||||||
@ -117,7 +117,7 @@ toHackApplication sampleRN hm env = do
|
|||||||
let rawHttpAccept = tryLookup "" "Accept" $ Hack.http env
|
let rawHttpAccept = tryLookup "" "Accept" $ Hack.http env
|
||||||
ctypes' = map TypeOther $ parseHttpAccept rawHttpAccept
|
ctypes' = map TypeOther $ parseHttpAccept rawHttpAccept
|
||||||
r <-
|
r <-
|
||||||
runHandler handler rr ctypes' >>=
|
runHandler handler rr sampleRN ctypes' >>=
|
||||||
either (applyErrorHandler sampleRN rr ctypes') return
|
either (applyErrorHandler sampleRN rr ctypes') return
|
||||||
responseToHackResponse (rawLanguages rr) r
|
responseToHackResponse (rawLanguages rr) r
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
module Yesod.Handler
|
module Yesod.Handler
|
||||||
( -- * Handler monad
|
( -- * Handler monad
|
||||||
Handler
|
Handler
|
||||||
|
, getYesod
|
||||||
, runHandler
|
, runHandler
|
||||||
, liftIO
|
, liftIO
|
||||||
--, ToHandler (..)
|
--, ToHandler (..)
|
||||||
@ -44,20 +45,20 @@ import Control.Monad.Attempt
|
|||||||
--import Data.Typeable
|
--import Data.Typeable
|
||||||
|
|
||||||
------ Handler monad
|
------ Handler monad
|
||||||
newtype Handler a = Handler {
|
newtype Handler yesod a = Handler {
|
||||||
unHandler :: RawRequest -> IO ([Header], HandlerContents a)
|
unHandler :: (RawRequest, yesod) -> IO ([Header], HandlerContents a)
|
||||||
}
|
}
|
||||||
data HandlerContents a =
|
data HandlerContents a =
|
||||||
forall e. Exception e => HCError e
|
forall e. Exception e => HCError e
|
||||||
| HCSpecial ErrorResult
|
| HCSpecial ErrorResult
|
||||||
| HCContent a
|
| HCContent a
|
||||||
|
|
||||||
instance Functor Handler where
|
instance Functor (Handler yesod) where
|
||||||
fmap = liftM
|
fmap = liftM
|
||||||
instance Applicative Handler where
|
instance Applicative (Handler yesod) where
|
||||||
pure = return
|
pure = return
|
||||||
(<*>) = ap
|
(<*>) = ap
|
||||||
instance Monad Handler where
|
instance Monad (Handler yesod) where
|
||||||
fail = failureString -- We want to catch all exceptions anyway
|
fail = failureString -- We want to catch all exceptions anyway
|
||||||
return x = Handler $ \_ -> return ([], HCContent x)
|
return x = Handler $ \_ -> return ([], HCContent x)
|
||||||
(Handler handler) >>= f = Handler $ \rr -> do
|
(Handler handler) >>= f = Handler $ \rr -> do
|
||||||
@ -68,23 +69,27 @@ instance Monad Handler where
|
|||||||
(HCSpecial e) -> return $ ([], HCSpecial e)
|
(HCSpecial e) -> return $ ([], HCSpecial e)
|
||||||
(HCContent a) -> unHandler (f a) rr
|
(HCContent a) -> unHandler (f a) rr
|
||||||
return (headers ++ headers', c')
|
return (headers ++ headers', c')
|
||||||
instance MonadIO Handler where
|
instance MonadIO (Handler yesod) where
|
||||||
liftIO i = Handler $ \_ -> i >>= \i' -> return ([], HCContent i')
|
liftIO i = Handler $ \_ -> i >>= \i' -> return ([], HCContent i')
|
||||||
instance Exception e => Failure e Handler where
|
instance Exception e => Failure e (Handler yesod) where
|
||||||
failure e = Handler $ \_ -> return ([], HCError e)
|
failure e = Handler $ \_ -> return ([], HCError e)
|
||||||
instance MonadRequestReader Handler where
|
instance MonadRequestReader (Handler yesod) where
|
||||||
askRawRequest = Handler $ \rr -> return ([], HCContent rr)
|
askRawRequest = Handler $ \(rr, _) -> return ([], HCContent rr)
|
||||||
invalidParam _pt _pn _pe = error "invalidParam"
|
invalidParam _pt _pn _pe = error "invalidParam"
|
||||||
authRequired = error "authRequired"
|
authRequired = error "authRequired"
|
||||||
|
|
||||||
|
getYesod :: Handler yesod yesod
|
||||||
|
getYesod = Handler $ \(_, yesod) -> return ([], HCContent yesod)
|
||||||
|
|
||||||
-- FIXME this is a stupid signature
|
-- FIXME this is a stupid signature
|
||||||
runHandler :: HasReps a
|
runHandler :: HasReps a
|
||||||
=> Handler a
|
=> Handler yesod a
|
||||||
-> RawRequest
|
-> RawRequest
|
||||||
|
-> yesod
|
||||||
-> [ContentType]
|
-> [ContentType]
|
||||||
-> IO (Either (ErrorResult, [Header]) Response)
|
-> IO (Either (ErrorResult, [Header]) Response)
|
||||||
runHandler (Handler handler) rr cts = do
|
runHandler (Handler handler) rr yesod cts = do
|
||||||
(headers, contents) <- handler rr
|
(headers, contents) <- handler (rr, yesod)
|
||||||
case contents of
|
case contents of
|
||||||
HCError e -> return $ Left (InternalError $ show e, headers)
|
HCError e -> return $ Left (InternalError $ show e, headers)
|
||||||
HCSpecial e -> return $ Left (e, headers)
|
HCSpecial e -> return $ Left (e, headers)
|
||||||
@ -171,15 +176,15 @@ runHandler eh wrapper ctypesAll (HandlerT inside) rr = do
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
------ Special handlers
|
------ Special handlers
|
||||||
errorResult :: ErrorResult -> Handler a
|
errorResult :: ErrorResult -> Handler yesod a
|
||||||
errorResult er = Handler $ \_ -> return ([], HCSpecial er)
|
errorResult er = Handler $ \_ -> return ([], HCSpecial er)
|
||||||
|
|
||||||
-- | Redirect to the given URL.
|
-- | Redirect to the given URL.
|
||||||
redirect :: String -> Handler a
|
redirect :: String -> Handler yesod a
|
||||||
redirect = errorResult . Redirect
|
redirect = errorResult . Redirect
|
||||||
|
|
||||||
-- | Return a 404 not found page. Also denotes no handler available.
|
-- | Return a 404 not found page. Also denotes no handler available.
|
||||||
notFound :: Handler a
|
notFound :: Handler yesod a
|
||||||
notFound = errorResult NotFound
|
notFound = errorResult NotFound
|
||||||
|
|
||||||
------- Headers
|
------- Headers
|
||||||
@ -187,16 +192,16 @@ notFound = errorResult NotFound
|
|||||||
addCookie :: Int -- ^ minutes to timeout
|
addCookie :: Int -- ^ minutes to timeout
|
||||||
-> String -- ^ key
|
-> String -- ^ key
|
||||||
-> String -- ^ value
|
-> String -- ^ value
|
||||||
-> Handler ()
|
-> Handler yesod ()
|
||||||
addCookie a b = addHeader . AddCookie a b
|
addCookie a b = addHeader . AddCookie a b
|
||||||
|
|
||||||
-- | Unset the cookie on the client.
|
-- | Unset the cookie on the client.
|
||||||
deleteCookie :: String -> Handler ()
|
deleteCookie :: String -> Handler yesod ()
|
||||||
deleteCookie = addHeader . DeleteCookie
|
deleteCookie = addHeader . DeleteCookie
|
||||||
|
|
||||||
-- | Set an arbitrary header on the client.
|
-- | Set an arbitrary header on the client.
|
||||||
header :: String -> String -> Handler ()
|
header :: String -> String -> Handler yesod ()
|
||||||
header a = addHeader . Header a
|
header a = addHeader . Header a
|
||||||
|
|
||||||
addHeader :: Header -> Handler ()
|
addHeader :: Header -> Handler yesod ()
|
||||||
addHeader h = Handler $ \_ -> return ([h], HCContent ())
|
addHeader h = Handler $ \_ -> return ([h], HCContent ())
|
||||||
|
|||||||
@ -60,7 +60,7 @@ instance Enumerable AuthResource where
|
|||||||
|
|
||||||
newtype RpxnowApiKey = RpxnowApiKey String
|
newtype RpxnowApiKey = RpxnowApiKey String
|
||||||
|
|
||||||
authHandler :: Maybe RpxnowApiKey -> AuthResource -> Verb -> Handler HtmlObject
|
authHandler :: Maybe RpxnowApiKey -> AuthResource -> Verb -> Handler y HtmlObject
|
||||||
authHandler _ Check Get = authCheck
|
authHandler _ Check Get = authCheck
|
||||||
authHandler _ Logout Get = authLogout
|
authHandler _ Logout Get = authLogout
|
||||||
authHandler _ Openid Get = authOpenidForm
|
authHandler _ Openid Get = authOpenidForm
|
||||||
@ -88,7 +88,7 @@ instance Show OIDFormReq where
|
|||||||
show (OIDFormReq (Just s) _) = "<p class='message'>" ++ encodeHtml s ++
|
show (OIDFormReq (Just s) _) = "<p class='message'>" ++ encodeHtml s ++
|
||||||
"</p>"
|
"</p>"
|
||||||
|
|
||||||
authOpenidForm :: Handler HtmlObject
|
authOpenidForm :: Handler y HtmlObject
|
||||||
authOpenidForm = do
|
authOpenidForm = do
|
||||||
m@(OIDFormReq _ dest) <- parseRequest
|
m@(OIDFormReq _ dest) <- parseRequest
|
||||||
let html =
|
let html =
|
||||||
@ -102,7 +102,7 @@ authOpenidForm = do
|
|||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
return $ toHtmlObject $ Html $ cs html
|
return $ toHtmlObject $ Html $ cs html
|
||||||
|
|
||||||
authOpenidForward :: Handler HtmlObject
|
authOpenidForward :: Handler y HtmlObject
|
||||||
authOpenidForward = do
|
authOpenidForward = do
|
||||||
oid <- getParam "openid"
|
oid <- getParam "openid"
|
||||||
env <- parseEnv
|
env <- parseEnv
|
||||||
@ -115,7 +115,7 @@ authOpenidForward = do
|
|||||||
redirect
|
redirect
|
||||||
res
|
res
|
||||||
|
|
||||||
authOpenidComplete :: Handler HtmlObject
|
authOpenidComplete :: Handler y HtmlObject
|
||||||
authOpenidComplete = do
|
authOpenidComplete = do
|
||||||
gets' <- rawGetParams <$> askRawRequest
|
gets' <- rawGetParams <$> askRawRequest
|
||||||
dest <- cookieParam "DEST"
|
dest <- cookieParam "DEST"
|
||||||
@ -141,7 +141,7 @@ chopHash ('#':rest) = rest
|
|||||||
chopHash x = x
|
chopHash x = x
|
||||||
|
|
||||||
rpxnowLogin :: String -- ^ api key
|
rpxnowLogin :: String -- ^ api key
|
||||||
-> Handler HtmlObject
|
-> Handler y HtmlObject
|
||||||
rpxnowLogin apiKey = do
|
rpxnowLogin apiKey = do
|
||||||
token <- anyParam "token"
|
token <- anyParam "token"
|
||||||
postDest <- postParam "dest"
|
postDest <- postParam "dest"
|
||||||
@ -157,7 +157,7 @@ rpxnowLogin apiKey = do
|
|||||||
header authCookieName $ Rpxnow.identifier ident
|
header authCookieName $ Rpxnow.identifier ident
|
||||||
redirect dest
|
redirect dest
|
||||||
|
|
||||||
authCheck :: Handler HtmlObject
|
authCheck :: Handler y HtmlObject
|
||||||
authCheck = do
|
authCheck = do
|
||||||
ident <- maybeIdentifier
|
ident <- maybeIdentifier
|
||||||
case ident of
|
case ident of
|
||||||
@ -167,7 +167,7 @@ authCheck = do
|
|||||||
, ("ident", i)
|
, ("ident", i)
|
||||||
]
|
]
|
||||||
|
|
||||||
authLogout :: Handler HtmlObject
|
authLogout :: Handler y HtmlObject
|
||||||
authLogout = do
|
authLogout = do
|
||||||
deleteCookie authCookieName
|
deleteCookie authCookieName
|
||||||
return $ toHtmlObject [("status", "loggedout")]
|
return $ toHtmlObject [("status", "loggedout")]
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import qualified Hack
|
|||||||
import Yesod.Request
|
import Yesod.Request
|
||||||
import Data.Time (UTCTime)
|
import Data.Time (UTCTime)
|
||||||
import Data.Convertible.Text (cs)
|
import Data.Convertible.Text (cs)
|
||||||
|
import Yesod.Yesod
|
||||||
|
|
||||||
data SitemapLoc = AbsLoc String | RelLoc String
|
data SitemapLoc = AbsLoc String | RelLoc String
|
||||||
data SitemapChangeFreq = Always
|
data SitemapChangeFreq = Always
|
||||||
@ -86,7 +87,7 @@ instance HasReps SitemapResponse where
|
|||||||
[ (TypeXml, cs . show)
|
[ (TypeXml, cs . show)
|
||||||
]
|
]
|
||||||
|
|
||||||
sitemap :: IO [SitemapUrl] -> Handler SitemapResponse
|
sitemap :: IO [SitemapUrl] -> Handler yesod SitemapResponse
|
||||||
sitemap urls' = do
|
sitemap urls' = do
|
||||||
env <- parseEnv
|
env <- parseEnv
|
||||||
-- FIXME
|
-- FIXME
|
||||||
@ -94,6 +95,8 @@ sitemap urls' = do
|
|||||||
urls <- liftIO urls'
|
urls <- liftIO urls'
|
||||||
return $ SitemapResponse req urls
|
return $ SitemapResponse req urls
|
||||||
|
|
||||||
robots :: Approot -> Handler Plain
|
robots :: Yesod yesod => Handler yesod Plain
|
||||||
robots (Approot ar) = do
|
robots = do
|
||||||
return $ plain $ "Sitemap: " ++ ar ++ "sitemap.xml"
|
yesod <- getYesod
|
||||||
|
return $ plain $ "Sitemap: " ++ unApproot (approot yesod)
|
||||||
|
++ "sitemap.xml"
|
||||||
|
|||||||
@ -40,11 +40,11 @@ fileLookupDir dir fp = do
|
|||||||
then Just <$> B.readFile fp'
|
then Just <$> B.readFile fp'
|
||||||
else return Nothing
|
else return Nothing
|
||||||
|
|
||||||
serveStatic :: FileLookup -> Verb -> Handler [(ContentType, Content)]
|
serveStatic :: FileLookup -> Verb -> Handler y [(ContentType, Content)]
|
||||||
serveStatic fl Get = getStatic fl
|
serveStatic fl Get = getStatic fl
|
||||||
serveStatic _ _ = notFound
|
serveStatic _ _ = notFound
|
||||||
|
|
||||||
getStatic :: FileLookup -> Handler [(ContentType, Content)]
|
getStatic :: FileLookup -> Handler y [(ContentType, Content)]
|
||||||
getStatic fl = do
|
getStatic fl = do
|
||||||
fp <- urlParam "filepath" -- FIXME check for ..
|
fp <- urlParam "filepath" -- FIXME check for ..
|
||||||
content <- liftIO $ fl fp
|
content <- liftIO $ fl fp
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
module Yesod.Resource
|
module Yesod.Resource
|
||||||
( ResourceName (..)
|
( ResourceName (..)
|
||||||
|
, ResourcePatternString
|
||||||
, fromString
|
, fromString
|
||||||
, checkPattern
|
, checkPattern
|
||||||
, validatePatterns
|
, validatePatterns
|
||||||
@ -92,7 +93,9 @@ class (Show a, Enumerable a) => ResourceName a where
|
|||||||
resourcePattern :: a -> String
|
resourcePattern :: a -> String
|
||||||
|
|
||||||
-- | Find the handler for each resource name/verb pattern.
|
-- | Find the handler for each resource name/verb pattern.
|
||||||
getHandler :: a -> Verb -> Handler [(ContentType, Content)] -- FIXME
|
getHandler :: a -> Verb -> Handler a [(ContentType, Content)] -- FIXME
|
||||||
|
|
||||||
|
type ResourcePatternString = String
|
||||||
|
|
||||||
type SMap = [(String, String)]
|
type SMap = [(String, String)]
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
-- | The basic typeclass for a Yesod application.
|
-- | The basic typeclass for a Yesod application.
|
||||||
module Yesod.Yesod
|
module Yesod.Yesod
|
||||||
( Yesod (..)
|
( Yesod (..)
|
||||||
, Handler
|
|
||||||
, toHackApp
|
, toHackApp
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -10,10 +9,10 @@ import Data.Object.Html (toHtmlObject)
|
|||||||
import Yesod.Response
|
import Yesod.Response
|
||||||
import Yesod.Request
|
import Yesod.Request
|
||||||
import Yesod.Constants
|
import Yesod.Constants
|
||||||
--import Yesod.Definitions
|
import Yesod.Definitions
|
||||||
--import Yesod.Resource (checkResourceName)
|
import Yesod.Resource
|
||||||
|
import Yesod.Handler
|
||||||
|
|
||||||
import Control.Applicative
|
|
||||||
--import Control.Monad (when)
|
--import Control.Monad (when)
|
||||||
|
|
||||||
import qualified Hack
|
import qualified Hack
|
||||||
@ -23,11 +22,12 @@ import Hack.Middleware.Gzip
|
|||||||
import Hack.Middleware.Jsonp
|
import Hack.Middleware.Jsonp
|
||||||
import Hack.Middleware.MethodOverride
|
import Hack.Middleware.MethodOverride
|
||||||
|
|
||||||
type Handler a v = a -> IO v -- FIXME
|
type ContentPair = (ContentType, Content)
|
||||||
type HandlerMap a = [(String, [ContentType] -> Handler a Content)]
|
|
||||||
|
|
||||||
class Yesod a where
|
class Yesod a where
|
||||||
handlers :: HandlerMap a
|
handlers ::
|
||||||
|
[(ResourcePatternString,
|
||||||
|
[(Verb, [ContentType] -> Handler a ContentPair)])]
|
||||||
|
|
||||||
-- | The encryption key to be used for encrypting client sessions.
|
-- | The encryption key to be used for encrypting client sessions.
|
||||||
encryptKey :: a -> IO Word256
|
encryptKey :: a -> IO Word256
|
||||||
@ -43,37 +43,36 @@ class Yesod a where
|
|||||||
]
|
]
|
||||||
|
|
||||||
-- | Output error response pages.
|
-- | Output error response pages.
|
||||||
errorHandler :: a -> RawRequest -> ErrorResult -> [ContentType] -> (ContentType, Content) -- FIXME better type sig?
|
errorHandler :: ErrorResult -> [ContentType] -> Handler a ContentPair
|
||||||
errorHandler = defaultErrorHandler
|
errorHandler = defaultErrorHandler
|
||||||
|
|
||||||
-- | Whether or not we should check for overlapping resource names.
|
-- | Whether or not we should check for overlapping resource names.
|
||||||
checkOverlaps :: a -> Bool
|
checkOverlaps :: a -> Bool
|
||||||
checkOverlaps = const True
|
checkOverlaps = const True
|
||||||
|
|
||||||
newtype MyIdentity a = MyIdentity { _unMyIdentity :: a }
|
-- | An absolute URL to the root of the application.
|
||||||
instance Functor MyIdentity where
|
approot :: a -> Approot
|
||||||
fmap f (MyIdentity a) = MyIdentity $ f a
|
|
||||||
instance Applicative MyIdentity where
|
|
||||||
pure = MyIdentity
|
|
||||||
(MyIdentity f) <*> (MyIdentity a) = MyIdentity $ f a
|
|
||||||
|
|
||||||
defaultErrorHandler :: a
|
defaultErrorHandler :: Yesod y
|
||||||
-> RawRequest
|
=> ErrorResult
|
||||||
-> ErrorResult
|
|
||||||
-> [ContentType]
|
-> [ContentType]
|
||||||
-> (ContentType, Content)
|
-> Handler y ContentPair
|
||||||
defaultErrorHandler _ rr NotFound = chooseRep $ toHtmlObject $
|
defaultErrorHandler NotFound cts = do
|
||||||
"Not found: " ++ show rr
|
rr <- askRawRequest
|
||||||
defaultErrorHandler _ _ (Redirect url) =
|
return $ chooseRep (toHtmlObject $ "Not found: " ++ show rr) cts
|
||||||
chooseRep $ toHtmlObject $ "Redirect to: " ++ url
|
defaultErrorHandler (Redirect url) cts =
|
||||||
defaultErrorHandler _ _ (InternalError e) =
|
return $ chooseRep (toHtmlObject $ "Redirect to: " ++ url) cts
|
||||||
chooseRep $ toHtmlObject $ "Internal server error: " ++ e
|
defaultErrorHandler PermissionDenied cts =
|
||||||
defaultErrorHandler _ _ (InvalidArgs ia) =
|
return $ chooseRep (toHtmlObject "Permission denied") cts
|
||||||
chooseRep $ toHtmlObject
|
defaultErrorHandler (InvalidArgs ia) cts =
|
||||||
|
return $ chooseRep (toHtmlObject
|
||||||
[ ("errorMsg", toHtmlObject "Invalid arguments")
|
[ ("errorMsg", toHtmlObject "Invalid arguments")
|
||||||
, ("messages", toHtmlObject ia)
|
, ("messages", toHtmlObject ia)
|
||||||
]
|
]) cts
|
||||||
defaultErrorHandler _ _ PermissionDenied =
|
defaultErrorHandler (InternalError e) cts =
|
||||||
chooseRep $ toHtmlObject "Permission denied"
|
return $ chooseRep (toHtmlObject
|
||||||
|
[ ("Internal server error", e)
|
||||||
|
]) cts
|
||||||
|
|
||||||
toHackApp :: Yesod y => y -> Hack.Application
|
toHackApp :: Yesod y => y -> Hack.Application
|
||||||
toHackApp a env = do
|
toHackApp a env = do
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user