Spock 0.3.0.0 → 0.4.0.0
raw patch · 5 files changed
+39/−31 lines, 5 filesdep ~aesondep ~scottydep ~text
Dependency ranges changed: aeson, scotty, text, wai, wai-extra
Files
- Spock.cabal +6/−6
- Web/Spock/Cookie.hs +7/−3
- Web/Spock/Monad.hs +11/−10
- Web/Spock/SessionManager.hs +6/−8
- Web/Spock/Types.hs +9/−4
Spock.cabal view
@@ -1,5 +1,5 @@ name: Spock-version: 0.3.0.0+version: 0.4.0.0 synopsis: Another Haskell web toolkit based on scotty description: This toolbox provides everything you need to get a quick start into web hacking with haskell: sessions, database helper, authentication and the power of scotty Homepage: https://github.com/agrafix/Spock@@ -19,14 +19,14 @@ Web.Spock.Cookie, Web.Spock.Types build-depends: base >= 4 && < 5,- scotty >= 0.5,- wai ==1.4.*,+ scotty >= 0.6,+ wai >=2.0, http-types ==0.8.*,- text ==0.11.*,+ text >= 0.11.3.1 && < 1.2, containers ==0.5.*, bytestring ==0.10.*, mtl ==2.1.*,- wai-extra ==1.3.*,+ wai-extra >=2.0.0.1, resourcet ==0.4.*, stm ==2.4.*, unordered-containers ==0.2.*,@@ -36,7 +36,7 @@ monad-control ==0.3.*, transformers ==0.3.*, xsd ==0.4.*,- aeson ==0.6.*,+ aeson >=0.6, resource-pool ==0.2.*, random ==1.* ghc-options: -fwarn-unused-imports
Web/Spock/Cookie.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} module Web.Spock.Cookie where +import Web.Spock.Types+ import Control.Arrow import Control.Monad.Trans import Data.Time@@ -12,7 +14,7 @@ import qualified Network.Wai as Wai -- | Read a cookie previously set in the users browser for your site-getCookie :: MonadIO m => T.Text -> ActionT m (Maybe T.Text)+getCookie :: (SpockError e, MonadIO m) => T.Text -> ActionT e m (Maybe T.Text) getCookie name = do req <- request return $ lookup "cookie" (Wai.requestHeaders req) >>=@@ -23,13 +25,15 @@ parseCookie = first T.init . T.breakOnEnd "=" -- | Set a cookie living for a given number of seconds-setCookie :: MonadIO m => T.Text -> T.Text -> NominalDiffTime -> ActionT m ()+setCookie :: (SpockError e, MonadIO m) => T.Text -> T.Text -> NominalDiffTime+ -> ActionT e m () setCookie name value validSeconds = do now <- liftIO getCurrentTime setCookie' name value (validSeconds `addUTCTime` now) -- | Set a cookie living until a specific 'UTCTime'-setCookie' :: MonadIO m => T.Text -> T.Text -> UTCTime -> ActionT m ()+setCookie' :: (SpockError e, MonadIO m) => T.Text -> T.Text -> UTCTime+ -> ActionT e m () setCookie' name value validUntil = let formattedTime = TL.pack $ formatTime defaultTimeLocale "%a, %d-%b-%Y %X %Z" validUntil
Web/Spock/Monad.hs view
@@ -1,16 +1,16 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-} module Web.Spock.Monad where import Web.Spock.Types -import Control.Applicative import Control.Monad import Control.Monad.Reader import Data.Pool import Data.Time.Clock ( UTCTime(..) ) import Web.Scotty.Trans import qualified Data.ByteString.Lazy as BSL-import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Lazy as TL import qualified Text.XML.XSD.DateTime as XSD@@ -35,18 +35,19 @@ getSessMgr :: MonadTrans t => t (WebStateM conn sess st) (SessionManager sess) getSessMgr = webM $ asks web_sessionMgr -instance Parsable T.Text where- parseParam = Right . TL.toStrict- instance Parsable BSL.ByteString where parseParam = Right . BSL.fromStrict . T.encodeUtf8 . TL.toStrict instance Parsable UTCTime where parseParam p = case join $ fmap XSD.toUTCTime $ XSD.dateTime (TL.toStrict p) of- Nothing -> Left $ TL.pack $ "Can't parse param (`" ++ show p ++ "`) as UTCTime!"- Just x -> Right x+ Nothing ->+ Left $ TL.pack $ "Can't parse param (`" ++ show p ++ "`) as UTCTime!"+ Just x ->+ Right x -instance (Functor a, Monad a, Applicative a) => Applicative (ActionT a) where- pure = return- (<*>) = ap+instance Integral a => Parsable a where+ parseParam p =+ let eInt :: Either TL.Text Integer+ eInt = readEither p+ in fmap fromInteger eInt
Web/Spock/SessionManager.hs view
@@ -34,24 +34,22 @@ , sm_deleteSession = deleteSessionImpl cacheHM } -createCookieSessionImpl :: MonadIO m- => UserSessions a- -> a- -> ActionT m ()+createCookieSessionImpl :: (SpockError e, MonadIO m) => UserSessions a -> a+ -> ActionT e m () createCookieSessionImpl sessRef val = do sess <- liftIO $ newSessionImpl sessRef val setCookie' _COOKIE_NAME_ (sess_id sess) (sess_validUntil sess) newSessionImpl :: UserSessions a- -> a- -> IO (Session a)+ -> a+ -> IO (Session a) newSessionImpl sessionRef content = do sess <- createSession content atomically $ modifyTVar sessionRef (\hm -> HM.insert (sess_id sess) sess hm) return sess -sessionFromCookieImpl :: MonadIO m- => UserSessions a -> ActionT m (Maybe (Session a))+sessionFromCookieImpl :: (SpockError e, MonadIO m) => UserSessions a+ -> ActionT e m (Maybe (Session a)) sessionFromCookieImpl sessionRef = do mSid <- getCookie _COOKIE_NAME_ case mSid of
Web/Spock/Types.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ConstraintKinds #-} module Web.Spock.Types where import Web.Scotty.Trans@@ -13,14 +14,17 @@ import Data.Time.Clock ( UTCTime(..), NominalDiffTime(..) ) import qualified Data.HashMap.Strict as HM import qualified Data.Text as T+import Data.Text.Lazy (Text) +type SpockError e = ScottyError e+ -- | Spock is supercharged Scotty, that's why the 'SpockM' is built on the -- ScottyT monad. Insive the SpockM monad, you may define routes and middleware.-type SpockM conn sess st a = ScottyT (WebStateM conn sess st) a+type SpockM conn sess st a = ScottyT Text (WebStateM conn sess st) a -- | The SpockAction is the monad of all route-actions. You have access -- to the database, session and state of your application.-type SpockAction conn sess st a = ActionT (WebStateM conn sess st) a+type SpockAction conn sess st a = ActionT Text (WebStateM conn sess st) a -- | If Spock should take care of connection pooling, you need to configure -- it depending on what you need.@@ -67,8 +71,9 @@ data SessionManager a = SessionManager { sm_loadSession :: SessionId -> IO (Maybe (Session a))- , sm_sessionFromCookie :: MonadIO m => ActionT m (Maybe (Session a))- , sm_createCookieSession :: MonadIO m => a -> ActionT m ()+ , sm_sessionFromCookie :: (SpockError e, MonadIO m)+ => ActionT e m (Maybe (Session a))+ , sm_createCookieSession :: (SpockError e, MonadIO m) => a -> ActionT e m () , sm_newSession :: a -> IO (Session a) , sm_deleteSession :: SessionId -> IO () }