packages feed

snap 0.11.3.1 → 0.12.0

raw patch · 26 files changed

+565/−289 lines, 26 filesdep ~heistdep ~snap-coredep ~snap-serverPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: heist, snap-core, snap-server

API changes (from Hackage documentation)

- Snap.Snaplet.Heist: addSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Initializer b v ()
- Snap.Snaplet.Heist.Interpreted: addSplices :: HasHeist b => [(Text, SnapletISplice b)] -> Initializer b v ()
- Snap.Snaplet.HeistNoClass: addSplices :: SnapletLens b (Heist b) -> [(Text, SnapletISplice b)] -> Initializer b v ()
- Snap.Snaplet.HeistNoClass: addSplices' :: SnapletLens (Snaplet b) (Heist b) -> [(Text, SnapletISplice b)] -> Initializer b v ()
- Snap.Snaplet.Session.Backends.CookieSession: instance (Serialize k, Serialize v, Hashable k, Eq k) => Serialize (HashMap k v)
- Snap.Snaplet.Session.Common: instance Serialize Text
+ Snap.Snaplet: failIfNotLocal :: MonadSnap m => m b -> m b
+ Snap.Snaplet: modifyMaster :: v -> Handler b v ()
+ Snap.Snaplet: snapletURL :: (Monad (m b v), MonadSnaplet m) => ByteString -> m b v ByteString
+ Snap.Snaplet.Heist: chooseMode :: HasHeist b => Handler b v a -> Handler b v a -> Handler b v a
+ Snap.Snaplet.Heist: gHeistServe :: HasHeist b => Handler b v ()
+ Snap.Snaplet.Heist: gHeistServeSingle :: HasHeist b => ByteString -> Handler b v ()
+ Snap.Snaplet.Heist: gRender :: HasHeist b => ByteString -> Handler b v ()
+ Snap.Snaplet.Heist: gRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()
+ Snap.Snaplet.Heist: getCurHeistConfig :: Snaplet (Heist b) -> Initializer b v (HeistConfig (Handler b b))
+ Snap.Snaplet.Heist: heistReloader :: Handler b (Heist b) ()
+ Snap.Snaplet.Heist: setInterpreted :: Snaplet (Heist b) -> Initializer b v ()
+ Snap.Snaplet.Heist.Generic: addConfig :: Snaplet (Heist b) -> HeistConfig (Handler b b) -> Initializer b v ()
+ Snap.Snaplet.Heist.Generic: addTemplates :: HasHeist b => Snaplet (Heist b) -> ByteString -> Initializer b v ()
+ Snap.Snaplet.Heist.Generic: addTemplatesAt :: HasHeist b => Snaplet (Heist b) -> ByteString -> FilePath -> Initializer b v ()
+ Snap.Snaplet.Heist.Generic: chooseMode :: HasHeist b => Handler b v a -> Handler b v a -> Handler b v a
+ Snap.Snaplet.Heist.Generic: class HasHeist b
+ Snap.Snaplet.Heist.Generic: clearHeistCache :: Heist b -> IO ()
+ Snap.Snaplet.Heist.Generic: data Heist b
+ Snap.Snaplet.Heist.Generic: gHeistServe :: HasHeist b => Handler b v ()
+ Snap.Snaplet.Heist.Generic: gHeistServeSingle :: HasHeist b => ByteString -> Handler b v ()
+ Snap.Snaplet.Heist.Generic: gRender :: HasHeist b => ByteString -> Handler b v ()
+ Snap.Snaplet.Heist.Generic: gRenderAs :: HasHeist b => ByteString -> ByteString -> Handler b v ()
+ Snap.Snaplet.Heist.Generic: heistInit :: FilePath -> SnapletInit b (Heist b)
+ Snap.Snaplet.Heist.Generic: heistInit' :: FilePath -> HeistConfig (Handler b b) -> SnapletInit b (Heist b)
+ Snap.Snaplet.Heist.Generic: heistLens :: HasHeist b => SnapletLens (Snaplet b) (Heist b)
+ Snap.Snaplet.Heist.Generic: modifyHeistState :: HasHeist b => (HeistState (Handler b b) -> HeistState (Handler b b)) -> Initializer b v ()
+ Snap.Snaplet.Heist.Generic: type SnapletCSplice b = SnapletHeist b IO (DList (Chunk (Handler b b)))
+ Snap.Snaplet.Heist.Generic: type SnapletHeist b m a = HeistT (Handler b b) m a
+ Snap.Snaplet.Heist.Generic: withHeistState :: HasHeist b => (HeistState (Handler b b) -> a) -> Handler b v a
+ Snap.Snaplet.HeistNoClass: Compiled :: DefaultMode
+ Snap.Snaplet.HeistNoClass: Interpreted :: DefaultMode
+ Snap.Snaplet.HeistNoClass: chooseMode :: MonadState (Heist b1) m => m b -> m b -> m b
+ Snap.Snaplet.HeistNoClass: data DefaultMode
+ Snap.Snaplet.HeistNoClass: gHeistServe :: Handler b (Heist b) ()
+ Snap.Snaplet.HeistNoClass: gHeistServeSingle :: ByteString -> Handler b (Heist b) ()
+ Snap.Snaplet.HeistNoClass: gRender :: ByteString -> Handler b (Heist b) ()
+ Snap.Snaplet.HeistNoClass: gRenderAs :: ByteString -> ByteString -> Handler b (Heist b) ()
+ Snap.Snaplet.HeistNoClass: getCurHeistConfig :: Snaplet (Heist b) -> Initializer b v (HeistConfig (Handler b b))
+ Snap.Snaplet.HeistNoClass: heistReloader :: Handler b (Heist b) ()
+ Snap.Snaplet.HeistNoClass: setInterpreted :: Snaplet (Heist b) -> Initializer b v ()
- Snap.Snaplet: snapletConfig :: Lens' (Snaplet s_aBoJ) SnapletConfig
+ Snap.Snaplet: snapletConfig :: Lens' (Snaplet s_aB5V) SnapletConfig
- Snap.Snaplet: snapletValue :: Lens (Snaplet s_aBoJ) (Snaplet s_aBpL) s_aBoJ s_aBpL
+ Snap.Snaplet: snapletValue :: Lens' (Snaplet s_aB5V) s_aB5V
- Snap.Snaplet.Auth: addAuthSplices :: HasHeist b => SnapletLens b (AuthManager b) -> Initializer b v ()
+ Snap.Snaplet.Auth: addAuthSplices :: HasHeist b => Snaplet (Heist b) -> SnapletLens b (AuthManager b) -> Initializer b v ()
- Snap.Snaplet.Auth: forceLogin :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure AuthUser)
+ Snap.Snaplet.Auth: forceLogin :: AuthUser -> Handler b (AuthManager b) (Either AuthFailure ())
- Snap.Snaplet.Auth: loginByRememberToken :: Handler b (AuthManager b) (Maybe AuthUser)
+ Snap.Snaplet.Auth: loginByRememberToken :: Handler b (AuthManager b) (Either AuthFailure AuthUser)
- Snap.Snaplet.Auth: loginByUsername :: ByteString -> Password -> Bool -> Handler b (AuthManager b) (Either AuthFailure AuthUser)
+ Snap.Snaplet.Auth: loginByUsername :: Text -> Password -> Bool -> Handler b (AuthManager b) (Either AuthFailure AuthUser)

Files

project_template/barebones/foo.cabal view
@@ -19,8 +19,8 @@     bytestring                >= 0.9.1 && < 0.11,     MonadCatchIO-transformers >= 0.2.1 && < 0.4,     mtl                       >= 2     && < 3,-    snap-core                 >= 0.9   && < 0.10,-    snap-server               >= 0.9   && < 0.10+    snap-core                 >= 0.9   && < 0.11,+    snap-server               >= 0.9   && < 0.11    if impl(ghc >= 6.12.0)     ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields -O2
project_template/default/foo.cabal view
@@ -24,12 +24,12 @@    Build-depends:     bytestring                >= 0.9.1   && < 0.11,-    heist                     >= 0.11    && < 0.12,+    heist                     >= 0.12    && < 0.13,     MonadCatchIO-transformers >= 0.2.1   && < 0.4,     mtl                       >= 2       && < 3,-    snap                      >= 0.11    && < 0.12,-    snap-core                 >= 0.9     && < 0.10,-    snap-server               >= 0.9     && < 0.10,+    snap                      >= 0.11    && < 0.13,+    snap-core                 >= 0.9     && < 0.11,+    snap-server               >= 0.9     && < 0.11,     snap-loader-static        >= 0.9     && < 0.10,     text                      >= 0.11    && < 0.12,     time                      >= 1.1     && < 1.5,@@ -42,7 +42,7 @@   else     build-depends:       base                      >= 4.4      && < 5,-      lens                      >= 3.7.6    && < 3.9+      lens                      >= 3.7.6    && < 3.10    if flag(development)     build-depends:
project_template/default/src/Site.hs view
@@ -83,6 +83,6 @@     a <- nestSnaplet "auth" auth $            initJsonFileAuthManager defAuthSettings sess "users.json"     addRoutes routes-    addAuthSplices auth+    addAuthSplices h auth     return $ App h s a 
project_template/tutorial/foo.cabal view
@@ -22,9 +22,9 @@     bytestring                >= 0.9.1   && < 0.11,     MonadCatchIO-transformers >= 0.2.1   && < 0.4,     mtl                       >= 2       && < 3,-    snap                      >= 0.11    && < 0.12,-    snap-core                 >= 0.9     && < 0.10,-    snap-server               >= 0.9     && < 0.10+    snap                      >= 0.11    && < 0.13,+    snap-core                 >= 0.9     && < 0.11,+    snap-server               >= 0.9     && < 0.11    if flag(old-base)     build-depends:@@ -33,7 +33,7 @@   else     build-depends:       base                      >= 4.4      && < 5,-      lens                      >= 3.7.6    && < 3.9+      lens                      >= 3.7.6    && < 3.10    if impl(ghc >= 6.12.0)     ghc-options: -threaded -Wall -fwarn-tabs -funbox-strict-fields -O2
snap.cabal view
@@ -1,5 +1,5 @@ name:           snap-version:        0.11.3.1+version:        0.12.0 synopsis:       Top-level package for the Snap Web Framework description:     This is the top-level package for the official Snap Framework libraries.@@ -111,6 +111,7 @@     Snap.Snaplet.Heist     Snap.Snaplet.HeistNoClass     Snap.Snaplet.Heist.Compiled+    Snap.Snaplet.Heist.Generic     Snap.Snaplet.Heist.Interpreted     Snap.Snaplet.Auth     Snap.Snaplet.Auth.Backends.JsonFile@@ -133,6 +134,7 @@     Snap.Snaplet.Auth.Types     Snap.Snaplet.Auth.Handlers     Snap.Snaplet.Auth.SpliceHelpers+    Snap.Snaplet.Heist.Internal     Snap.Snaplet.Internal.Initializer     Snap.Snaplet.Internal.LensT     Snap.Snaplet.Internal.Lensed@@ -157,14 +159,14 @@     filepath                  >= 1.1      && < 1.4,     -- Blacklist bad versions of hashable     hashable                  (>= 1.1 && < 1.2) || (>= 1.2.0.6 && <1.3),-    heist                     >= 0.11     && < 0.12,+    heist                     >= 0.12     && < 0.13,     logict                    >= 0.4.2    && < 0.7,     mtl                       >  2.0      && < 2.2,     mwc-random                >= 0.8      && < 0.13,     pwstore-fast              >= 2.2      && < 2.4,     regex-posix               >= 0.95     && < 1,-    snap-core                 >= 0.9      && < 0.10,-    snap-server               >= 0.9      && < 0.10,+    snap-core                 >= 0.9      && < 0.11,+    snap-server               >= 0.9      && < 0.11,     stm                       >= 2.2      && < 2.5,     syb                       >= 0.1      && < 0.5,     text                      >= 0.11     && < 0.12,@@ -231,6 +233,9 @@     snap-server         >= 0.9     && < 0.11,     template-haskell    >= 2.2     && < 2.9,     text                >= 0.11    && < 0.12++  extensions:+    OverloadedStrings    ghc-prof-options: -prof -auto-all 
src/Snap/Snaplet.hs view
@@ -64,6 +64,7 @@   , getSnapletDescription   , getSnapletUserConfig   , getSnapletRootURL+  , snapletURL   , getRoutePattern   , setRoutePattern @@ -100,7 +101,9 @@    -- * Handlers   , Handler+  , failIfNotLocal   , reloadSite+  , modifyMaster   , bracketHandler    -- * Serving Applications
src/Snap/Snaplet/Auth/Handlers.hs view
@@ -59,7 +59,7 @@ ------------------------------------------------------------------------------ -- | Lookup a user by her username, check given password and perform login ---loginByUsername :: ByteString       -- ^ Username/login for user+loginByUsername :: Text             -- ^ Username/login for user                 -> Password         -- ^ Should be ClearText                 -> Bool             -- ^ Set remember token?                 -> Handler b (AuthManager b) (Either AuthFailure AuthUser)@@ -79,7 +79,7 @@                      -> t                      -> Handler b (AuthManager b) (Either AuthFailure AuthUser)     loginByUsername' sk cn rp r =-        liftIO (lookupByLogin r $ decodeUtf8 unm) >>=+        liftIO (lookupByLogin r unm) >>=         maybe (return $! Left UserNotFound) found        where@@ -108,16 +108,18 @@ ------------------------------------------------------------------------------ -- | Remember user from the remember token if possible and perform login ---loginByRememberToken :: Handler b (AuthManager b) (Maybe AuthUser)+loginByRememberToken :: Handler b (AuthManager b) (Either AuthFailure AuthUser) loginByRememberToken = withBackend $ \impl -> do     key         <- gets siteKey     cookieName_ <- gets rememberCookieName     period      <- gets rememberPeriod -    runMaybeT $ do-        token <- MaybeT $ getRememberToken key cookieName_ period-        user  <- MaybeT $ liftIO $ lookupByRememberToken impl-                                 $ decodeUtf8 token+    runEitherT $ do+        token <- noteT (AuthError "loginByRememberToken: no remember token") $+                   MaybeT $ getRememberToken key cookieName_ period+        user  <- noteT (AuthError "loginByRememberToken: no remember token") $+                   MaybeT $ liftIO $ lookupByRememberToken impl+                                   $ decodeUtf8 token         lift $ forceLogin user         return user @@ -142,7 +144,7 @@     s   <- gets session     uid <- withTop s getSessionUserId     case uid of-      Nothing -> loginByRememberToken+      Nothing -> hush <$> loginByRememberToken       Just uid' -> liftIO $ lookupByUserId r uid'  @@ -286,14 +288,14 @@ -- who she says she is. -- forceLogin :: AuthUser       -- ^ An existing user, somehow looked up from db-           -> Handler b (AuthManager b) (Either AuthFailure AuthUser)+           -> Handler b (AuthManager b) (Either AuthFailure ()) forceLogin u = do     s <- gets session     withSession s $         case userId u of           Just x -> do             withTop s (setSessionUserId x)-            return $ Right u+            return $ Right ()           Nothing -> return . Left $                      AuthError $ "forceLogin: Can't force the login of a user "                                    ++ "without userId"@@ -450,7 +452,8 @@     password <- noteT PasswordMissing $ hoistMaybe mbPassword     username <- noteT UsernameMissing $ hoistMaybe mbUsername -    EitherT $ loginByUsername username (ClearText password) remember+    EitherT $ loginByUsername (decodeUtf8 username)+                              (ClearText password) remember   ------------------------------------------------------------------------------
src/Snap/Snaplet/Auth/SpliceHelpers.hs view
@@ -52,14 +52,17 @@ -- \<loggedInUser\> addAuthSplices   :: HasHeist b-  => SnapletLens b (AuthManager b)+  => Snaplet (Heist b)+  -> SnapletLens b (AuthManager b)       -- ^ A lens reference to 'AuthManager'   -> Initializer b v ()-addAuthSplices auth = addSplices-    [ ("ifLoggedIn", ifLoggedIn auth)-    , ("ifLoggedOut", ifLoggedOut auth)-    , ("loggedInUser", loggedInUser auth)-    ]+addAuthSplices h auth = addConfig h $ mempty+    { hcInterpretedSplices = [ ("ifLoggedIn", ifLoggedIn auth)+                             , ("ifLoggedOut", ifLoggedOut auth)+                             , ("loggedInUser", loggedInUser auth)+                             ]+    , hcCompiledSplices = compiledAuthSplices auth+    }   ------------------------------------------------------------------------------
src/Snap/Snaplet/Heist.hs view
@@ -13,15 +13,23 @@   -- $initializerSection   , heistInit   , heistInit'+  , Unclassed.heistReloader+  , Unclassed.setInterpreted+  , Unclassed.getCurHeistConfig    , addTemplates   , addTemplatesAt   , Unclassed.addConfig   , modifyHeistState   , withHeistState-  , addSplices    -- * Handler Functions   -- $handlerSection+  , gRender+  , gRenderAs+  , gHeistServe+  , gHeistServeSingle+  , chooseMode+   , cRender   , cRenderAs   , cHeistServe@@ -46,14 +54,15 @@  ------------------------------------------------------------------------------ import           Prelude hiding (id, (.))+import           Control.Monad.State import           Data.ByteString (ByteString) import           Data.Text (Text) import           Heist ------------------------------------------------------------------------------ import           Snap.Snaplet+import           Snap.Snaplet.Heist.Internal import qualified Snap.Snaplet.HeistNoClass as Unclassed-import           Snap.Snaplet.HeistNoClass ( Heist-                                           , heistInit+import           Snap.Snaplet.HeistNoClass ( heistInit                                            , heistInit'                                            , clearHeistCache                                            )@@ -72,7 +81,7 @@ -- > -- > appInit = makeSnaplet "app" "" Nothing $ do -- >     h <- nestSnaplet "heist" heist $ heistInit "templates"--- >     addSplices myAppSplices+-- >     addConfig h heistConfigWithMyAppSplices -- >     return $ App h class HasHeist b where     -- | A lens to the Heist snaplet.  The b parameter to Heist will@@ -116,19 +125,6 @@   --------------------------------------------------------------------------------- | Allows snaplets to add interpreted splices.------ NOTE: The splices added with this function will not work if you render your--- templates with cRender.  To add splices that work with cRender, you have to--- use the addConfig function to add compiled splices or load time splices.-addSplices :: (HasHeist b)-           => [(Text, Unclassed.SnapletISplice b)]-               -- ^ Splices to bind-           -> Initializer b v ()-addSplices = Unclassed.addSplices' heistLens--------------------------------------------------------------------------------- -- | More general function allowing arbitrary HeistState modification. modifyHeistState :: (HasHeist b)                  => (HeistState (Handler b b) -> HeistState (Handler b b))@@ -148,35 +144,70 @@  -- $handlerSection -- This section contains functions in the 'Handler' monad that you'll use in--- processing requests.  Functions beginning with a 'c' prefix use compiled--- template rendering.  The other functions use the older interpreted--- rendering.  Splices added with addSplices will only work if you use+-- processing requests.  Functions beginning with a 'g' prefix use generic+-- rendering that checks the preferred rendering mode and chooses+-- appropriately.  Functions beginning with a 'c' prefix use compiled template+-- rendering.  The other functions use the older interpreted rendering.+-- Interpreted splices added with addConfig will only work if you use -- interpreted rendering.+--+-- The generic functions are useful if you are writing general snaplets that+-- use heist, but need to work for applications that use either interpreted+-- or compiled mode.   --------------------------------------------------------------------------------- | Renders a template as text\/html. If the given template is not found,--- this returns 'empty'.-render :: HasHeist b-       => ByteString-           -- ^ Template name-       -> Handler b v ()-render t = withTop' heistLens (Unclassed.render t)+-- | Generic version of 'render'/'cRender'.+gRender :: HasHeist b+        => ByteString+            -- ^ Template name+        -> Handler b v ()+gRender t = withTop' heistLens (Unclassed.gRender t)   --------------------------------------------------------------------------------- | Renders a template as the given content type.  If the given template--- is not found, this returns 'empty'.-renderAs :: HasHeist b-         => ByteString-             -- ^ Content type to render with-         -> ByteString-             -- ^ Template name-         -> Handler b v ()-renderAs ct t = withTop' heistLens (Unclassed.renderAs ct t)+-- | Generic version of 'renderAs'/'cRenderAs'.+gRenderAs :: HasHeist b+          => ByteString+              -- ^ Content type to render with+          -> ByteString+              -- ^ Template name+          -> Handler b v ()+gRenderAs ct t = withTop' heistLens (Unclassed.gRenderAs ct t)   ------------------------------------------------------------------------------+-- | Generic version of 'heistServe'/'cHeistServe'.+gHeistServe :: HasHeist b => Handler b v ()+gHeistServe = withTop' heistLens Unclassed.gHeistServe+++------------------------------------------------------------------------------+-- | Generic version of 'heistServeSingle'/'cHeistServeSingle'.+gHeistServeSingle :: HasHeist b+                  => ByteString+                      -- ^ Template name+                  -> Handler b v ()+gHeistServeSingle t = withTop' heistLens (Unclassed.gHeistServeSingle t)+++------------------------------------------------------------------------------+-- | Chooses between a compiled action and an interpreted action based on the+-- configured default.+chooseMode :: HasHeist b+           => Handler b v a+               -- ^ A compiled action+           -> Handler b v a+               -- ^ An interpreted action+           -> Handler b v a+chooseMode cAction iAction = do+    mode <- withTop' heistLens $ gets _defMode+    case mode of+      Unclassed.Compiled -> cAction+      Unclassed.Interpreted -> iAction+++------------------------------------------------------------------------------ -- | Renders a compiled template as text\/html. If the given template is not -- found, this returns 'empty'. cRender :: HasHeist b@@ -199,6 +230,44 @@   ------------------------------------------------------------------------------+-- | A compiled version of 'heistServe'.+cHeistServe :: HasHeist b => Handler b v ()+cHeistServe = withTop' heistLens Unclassed.cHeistServe+++------------------------------------------------------------------------------+-- | Analogous to 'fileServeSingle'. If the given template is not found,+-- this throws an error.+cHeistServeSingle :: HasHeist b+                 => ByteString+                     -- ^ Template name+                 -> Handler b v ()+cHeistServeSingle t = withTop' heistLens (Unclassed.cHeistServeSingle t)+++------------------------------------------------------------------------------+-- | Renders a template as text\/html. If the given template is not found,+-- this returns 'empty'.+render :: HasHeist b+       => ByteString+           -- ^ Template name+       -> Handler b v ()+render t = withTop' heistLens (Unclassed.render t)+++------------------------------------------------------------------------------+-- | Renders a template as the given content type.  If the given template+-- is not found, this returns 'empty'.+renderAs :: HasHeist b+         => ByteString+             -- ^ Content type to render with+         -> ByteString+             -- ^ Template name+         -> Handler b v ()+renderAs ct t = withTop' heistLens (Unclassed.renderAs ct t)+++------------------------------------------------------------------------------ -- | A handler that serves all the templates (similar to 'serveDirectory'). -- If the template specified in the request path is not found, it returns -- 'empty'.  Also, this function does not serve any templates beginning with@@ -219,22 +288,6 @@                      -- ^ Template name                  -> Handler b v () heistServeSingle t = withTop' heistLens (Unclassed.heistServeSingle t)------------------------------------------------------------------------------------ | A compiled version of 'heistServe'.-cHeistServe :: HasHeist b => Handler b v ()-cHeistServe = withTop' heistLens Unclassed.cHeistServe------------------------------------------------------------------------------------ | Analogous to 'fileServeSingle'. If the given template is not found,--- this throws an error.-cHeistServeSingle :: HasHeist b-                 => ByteString-                     -- ^ Template name-                 -> Handler b v ()-cHeistServeSingle t = withTop' heistLens (Unclassed.cHeistServeSingle t)   ------------------------------------------------------------------------------
+ src/Snap/Snaplet/Heist/Generic.hs view
@@ -0,0 +1,37 @@+{-|++A module exporting only generic functions that choose between compiled and+interpreted mode based on the setting specified in the initializer.  This+module is most useful for writitng general snaplets that use Heist and are+meant to be used in applications that might use either interpreted or compiled+templates.++-}+module Snap.Snaplet.Heist.Generic+  ( Heist+  , HasHeist(..)+  , SnapletHeist+  , SnapletCSplice++  -- * Initializer Functions+  -- $initializerSection+  , heistInit+  , heistInit'+  , addTemplates+  , addTemplatesAt+  , addConfig+  , modifyHeistState+  , withHeistState++  -- * Handler Functions+  -- $handlerSection+  , gRender+  , gRenderAs+  , gHeistServe+  , gHeistServeSingle+  , chooseMode++  , clearHeistCache+  ) where++import Snap.Snaplet.Heist
+ src/Snap/Snaplet/Heist/Internal.hs view
@@ -0,0 +1,30 @@+module Snap.Snaplet.Heist.Internal where++import           Prelude hiding ((.), id)+import           Control.Lens+import           Data.IORef+import           Heist+import           Heist.Splices.Cache++import           Snap.Snaplet+++data DefaultMode = Compiled | Interpreted+++------------------------------------------------------------------------------+-- | The state for the Heist snaplet.  To use the Heist snaplet in your app+-- include this in your application state and use 'heistInit' to initialize+-- it.  The type parameter b will typically be the base state type for your+-- application.+data Heist b = Configuring+                 { _heistConfig :: IORef (HeistConfig (Handler b b), DefaultMode)+                 }+             | Running+                 { _masterConfig :: HeistConfig (Handler b b)+                 , _heistState   :: HeistState (Handler b b)+                 , _heistCTS     :: CacheTagState+                 , _defMode      :: DefaultMode+                 }++makeLenses ''Heist
src/Snap/Snaplet/Heist/Interpreted.hs view
@@ -21,7 +21,6 @@   , addConfig   , modifyHeistState   , withHeistState-  , addSplices    -- * Handler Functions   -- $handlerSection
src/Snap/Snaplet/HeistNoClass.hs view
@@ -5,7 +5,6 @@ {-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE FlexibleContexts           #-} {-# LANGUAGE FunctionalDependencies     #-}-{-# LANGUAGE TypeFamilies               #-} {-# LANGUAGE TypeSynonymInstances       #-}  {-|@@ -17,8 +16,12 @@ -} module Snap.Snaplet.HeistNoClass   ( Heist+  , DefaultMode(..)   , heistInit   , heistInit'+  , heistReloader+  , setInterpreted+  , getCurHeistConfig    , clearHeistCache    , addTemplates@@ -27,9 +30,13 @@   , modifyHeistState'   , withHeistState   , withHeistState'-  , addSplices-  , addSplices' +  , gRender+  , gRenderAs+  , gHeistServe+  , gHeistServeSingle+  , chooseMode+   , addConfig   , cRender   , cRenderAs@@ -55,8 +62,8 @@ import           Prelude hiding ((.), id) import           Control.Applicative import           Control.Category-import           Control.Comonad import           Control.Error+import           Control.Lens import           Control.Monad.Reader import           Control.Monad.State import           Data.ByteString (ByteString)@@ -76,30 +83,18 @@ import           Heist.Splices.Cache  import           Snap.Snaplet+import           Snap.Snaplet.Heist.Internal import           Snap.Core import           Snap.Util.FileServe   --------------------------------------------------------------------------------- | The state for the Heist snaplet.  To use the Heist snaplet in your app--- include this in your application state and use 'heistInit' to initialize--- it.  The type parameter b will typically be the base state type for your--- application.-data Heist b = Configuring-                 { _heistConfig :: IORef (HeistConfig (Handler b b)) }-             | Running-                 { _heistState    :: HeistState (Handler b b)-                 , _heistCTS      :: CacheTagState-                 }--------------------------------------------------------------------------------- changeState :: (HeistState (Handler a a) -> HeistState (Handler a a))             -> Heist a             -> Heist a changeState _ (Configuring _)  =     error "changeState: HeistState has not been initialized"-changeState f (Running hs cts) = Running (f hs) cts+changeState f (Running hc hs cts dm) = Running hc (f hs) cts dm   ------------------------------------------------------------------------------@@ -110,6 +105,22 @@ clearHeistCache = clearCacheTagState . _heistCTS  +------------------------------------------------------------------------------+-- | Handler that triggers a template reload.  For large sites, this can be+-- desireable because it may be much quicker than the full site reload+-- provided at the /admin/reload route.  This allows you to reload only the+-- heist templates  This handler is automatically set up by heistInit, but if+-- you use heistInit', then you can create your own route with it.+heistReloader :: Handler b (Heist b) ()+heistReloader = do+    h <- get+    ehs <- liftIO $ runEitherT $ initHeist $ _masterConfig h+    either (writeText . T.pack . unlines)+           (\hs -> do writeText "Heist reloaded."+                      modifyMaster $ set heistState hs h)+           ehs++                          -----------------------------                          -- SnapletSplice functions --                          -----------------------------@@ -134,14 +145,17 @@ ------------------------------------------------------------------------------ -- | The 'Initializer' for 'Heist'. This function is a convenience wrapper -- around `heistInit'` that uses defaultHeistState and sets up routes for all--- the templates.+-- the templates.  It sets up a \"heistReload\" route that reloads the heist+-- templates when you request it from localhost. heistInit :: FilePath               -- ^ Path to templates           -> SnapletInit b (Heist b) heistInit templateDir = do     makeSnaplet "heist" "" Nothing $ do         hs <- heistInitWorker templateDir defaultConfig-        addRoutes [ ("", heistServe) ]+        addRoutes [ ("", heistServe)+                  , ("heistReload", failIfNotLocal heistReloader)+                  ]         return hs   where     defaultConfig = mempty { hcLoadTimeSplices = defaultLoadTimeSplices }@@ -161,8 +175,8 @@   --------------------------------------------------------------------------------- | Internal worker function used by variantsof heistInit.  This is necessary--- because of the divide between SnapletInit and Initializer.+-- | Internal worker function used by variants of heistInit.  This is+-- necessary because of the divide between SnapletInit and Initializer. heistInitWorker :: FilePath                 -> HeistConfig (Handler b b)                 -> Initializer b (Heist b) (Heist b)@@ -171,29 +185,47 @@     let tDir = snapletPath </> templateDir     templates <- liftIO $ runEitherT (loadTemplates tDir) >>=                           either (error . concat) return-    let config = initialConfig `mappend` mempty { hcTemplates = templates }     printInfo $ T.pack $ unwords         [ "...loaded"         , (show $ Map.size templates)         , "templates from"         , tDir         ]-    ref <- liftIO $ newIORef config+    let config = initialConfig `mappend`+                 mempty { hcTemplateLocations = [loadTemplates tDir] }+    ref <- liftIO $ newIORef (config, Compiled)++    -- FIXME This runs after all the initializers, but before post init+    -- hooks registered by other snaplets.     addPostInitHook finalLoadHook     return $ Configuring ref   ------------------------------------------------------------------------------+-- | Sets the snaplet to default to interpreted mode.  Initially, the+-- initializer sets the value to compiled mode.  This function allows you to+-- override that setting.  Note that this is just a default.  It only has an+-- effect if you use one of the generic functions: 'gRender', 'gRenderAs',+-- 'gHeistServe', or 'gHeistServeSingle'.  If you call the non-generic+-- versions directly, then this value will not be checked and you will get the+-- mode implemented by the function you called.+setInterpreted :: Snaplet (Heist b) -> Initializer b v ()+setInterpreted h = +    liftIO $ atomicModifyIORef (_heistConfig $ view snapletValue h)+        (\(hc,_) -> ((hc,Interpreted),()))+++------------------------------------------------------------------------------ -- | Hook that converts the Heist type from Configuring to Running at the end -- of initialization. finalLoadHook :: Heist b -> EitherT Text IO (Heist b) finalLoadHook (Configuring ref) = do-    hc <- lift $ readIORef ref+    (hc,dm) <- lift $ readIORef ref     (hs,cts) <- toTextErrors $ initHeistWithCacheTag hc-    return $ Running hs cts+    return $ Running hc hs cts dm   where     toTextErrors = bimapEitherT (T.pack . intercalate "\n") id-finalLoadHook (Running _ _) = left "finalLoadHook called while running"+finalLoadHook (Running _ _ _ _) = left "finalLoadHook called while running"   ------------------------------------------------------------------------------@@ -226,10 +258,10 @@     rootUrl <- getSnapletRootURL     let fullPrefix = (T.unpack $ decodeUtf8 rootUrl) </>                      (T.unpack $ decodeUtf8 urlPrefix)-        addPrefix = return . addTemplatePathPrefix-                               (encodeUtf8 $ T.pack fullPrefix)+        addPrefix = addTemplatePathPrefix+                      (encodeUtf8 $ T.pack fullPrefix)     ts <- liftIO $ runEitherT (loadTemplates templateDir) >>=-                   either (error . concat) addPrefix+                   either (error . concat) return     printInfo $ T.pack $ unwords         [ "...adding"         , (show $ Map.size ts)@@ -238,10 +270,22 @@         , "with route prefix"         , fullPrefix ++ "/"         ]-    liftIO $ atomicModifyIORef (_heistConfig $ extract h)-        (\hc -> (hc `mappend` mempty { hcTemplates = ts }, ()))+    let locations = [liftM addPrefix $ loadTemplates templateDir]+        hc' = mempty { hcTemplateLocations = locations }+    liftIO $ atomicModifyIORef (_heistConfig $ view snapletValue h)+        (\(hc,dm) -> ((hc `mappend` hc', dm), ()))  +getCurHeistConfig :: Snaplet (Heist b)+                  -> Initializer b v (HeistConfig (Handler b b))+getCurHeistConfig h = case view snapletValue h of+    Configuring ref -> do+        (hc, _) <- liftIO $ readIORef ref+        return hc+    Running _ _ _ _ ->+        error "Can't get HeistConfig after heist is initialized."+    + ------------------------------------------------------------------------------ modifyHeistState' :: SnapletLens (Snaplet b) (Heist b)                   -> (HeistState (Handler b b) -> HeistState (Handler b b))@@ -280,30 +324,15 @@ addConfig :: Snaplet (Heist b)           -> HeistConfig (Handler b b)           -> Initializer b v ()-addConfig h hc = case extract h of+addConfig h hc = case view snapletValue h of     Configuring ref ->-        liftIO $ atomicModifyIORef ref (\hc1 -> (hc1 `mappend` hc, ()))-    Running _ _ -> do+        liftIO $ atomicModifyIORef ref+                   (\(hc1,dm) -> ((hc1 `mappend` hc, dm), ()))+    Running _ _ _ _ -> do         printInfo "finalLoadHook called while running"         error "this shouldn't happen"  --------------------------------------------------------------------------------addSplices' :: SnapletLens (Snaplet b) (Heist b)-            -> [(Text, SnapletISplice b)]-            -> Initializer b v ()-addSplices' heist splices = do-    withTop' heist $ addPostInitHook $-        return . changeState (I.bindSplices splices)----------------------------------------------------------------------------------addSplices :: SnapletLens b (Heist b)-           -> [(Text, SnapletISplice b)]-           -> Initializer b v ()-addSplices heist splices = addSplices' (subSnaplet heist) splices--                             -----------------------                             -- Handler functions --                             -----------------------@@ -314,7 +343,7 @@              -> ByteString              -> Handler b (Heist b) () iRenderHelper c t = do-    (Running hs _) <- get+    (Running _ hs _ _) <- get     withTop' id $ I.renderTemplate hs t >>= maybe pass serve   where     serve (b, mime) = do@@ -328,7 +357,7 @@               -> ByteString               -> Handler b (Heist b) () cRenderHelper c t = do-    (Running hs _) <- get+    (Running _ hs _ _) <- get     withTop' id $ maybe pass serve $ C.renderTemplate hs t   where     serve (b, mime) = do@@ -337,6 +366,15 @@   ------------------------------------------------------------------------------+serveURI :: Handler b (Heist b) ByteString+serveURI = do+    p <- getSafePath+    -- Allows users to prefix template filenames with an underscore to prevent+    -- the template from being served.+    if take 1 p == "_" then pass else return $ B.pack p+++------------------------------------------------------------------------------ render :: ByteString            -- ^ Name of the template        -> Handler b (Heist b) ()@@ -353,6 +391,18 @@   ------------------------------------------------------------------------------+heistServe :: Handler b (Heist b) ()+heistServe =+    ifTop (render "index") <|> (render =<< serveURI)+++------------------------------------------------------------------------------+heistServeSingle :: ByteString -> Handler b (Heist b) ()+heistServeSingle t =+    render t <|> error ("Template " ++ show t ++ " not found.")+++------------------------------------------------------------------------------ cRender :: ByteString            -- ^ Name of the template         -> Handler b (Heist b) ()@@ -369,36 +419,65 @@   -------------------------------------------------------------------------------serveURI :: Handler b (Heist b) ByteString-serveURI = do-    p <- getSafePath-    -- Allows users to prefix template filenames with an underscore to prevent-    -- the template from being served.-    if take 1 p == "_" then pass else return $ B.pack p+cHeistServe :: Handler b (Heist b) ()+cHeistServe =+    ifTop (cRender "index") <|> (cRender =<< serveURI)   -------------------------------------------------------------------------------heistServe :: Handler b (Heist b) ()-heistServe =-    ifTop (render "index") <|> (render =<< serveURI)+cHeistServeSingle :: ByteString -> Handler b (Heist b) ()+cHeistServeSingle t =+    cRender t <|> error ("Template " ++ show t ++ " not found.")   -------------------------------------------------------------------------------heistServeSingle :: ByteString -> Handler b (Heist b) ()-heistServeSingle t =-    render t <|> error ("Template " ++ show t ++ " not found.")+-- | Chooses between a compiled action and an interpreted action based on the+-- configured default.+chooseMode :: MonadState (Heist b1) m+           => m b+               -- ^ A compiled action+           -> m b+               -- ^ An interpreted action+           -> m b+chooseMode cAction iAction = do+    mode <- gets _defMode+    case mode of+      Compiled -> cAction+      Interpreted -> iAction   -------------------------------------------------------------------------------cHeistServe :: Handler b (Heist b) ()-cHeistServe =-    ifTop (cRender "index") <|> (cRender =<< serveURI)+-- | Like render/cRender, but chooses between the two appropriately based on+-- the default mode.+gRender :: ByteString+           -- ^ Name of the template+        -> Handler b (Heist b) ()+gRender t = chooseMode (cRender t) (render t)   -------------------------------------------------------------------------------cHeistServeSingle :: ByteString -> Handler b (Heist b) ()-cHeistServeSingle t =-    cRender t <|> error ("Template " ++ show t ++ " not found.")+-- | Like renderAs/cRenderAs, but chooses between the two appropriately based+-- on the default mode.+gRenderAs :: ByteString+             -- ^ Content type+          -> ByteString+             -- ^ Name of the template+          -> Handler b (Heist b) ()+gRenderAs ct t = chooseMode (cRenderAs ct t) (renderAs ct t)+++------------------------------------------------------------------------------+-- | Like heistServe/cHeistServe, but chooses between the two appropriately+-- based on the default mode.+gHeistServe :: Handler b (Heist b) ()+gHeistServe = chooseMode cHeistServe heistServe+++------------------------------------------------------------------------------+-- | Like heistServeSingle/cHeistServeSingle, but chooses between the two+-- appropriately based on the default mode.+gHeistServeSingle :: ByteString -> Handler b (Heist b) ()+gHeistServeSingle t = chooseMode (cHeistServeSingle t) (heistServeSingle t)   ------------------------------------------------------------------------------
src/Snap/Snaplet/Internal/Initializer.hs view
@@ -22,6 +22,7 @@   , loadAppConfig   , printInfo   , getRoutes+  , modifyMaster   ) where  import           Prelude hiding (catch)@@ -89,9 +90,9 @@ -- | Converts a plain hook into a Snaplet hook. toSnapletHook :: (v -> EitherT Text IO v)               -> (Snaplet v -> EitherT Text IO (Snaplet v))-toSnapletHook f (Snaplet cfg val) = do+toSnapletHook f (Snaplet cfg  reset val) = do     val' <- f val-    return $! Snaplet cfg val'+    return $! Snaplet cfg reset val'   ------------------------------------------------------------------------------@@ -239,11 +240,15 @@ ------------------------------------------------------------------------------ -- | Internal function that gets the SnapletConfig out of the initializer -- state and uses it to create a (Snaplet a).-mkSnaplet :: Initializer b v a -> Initializer b v (Snaplet a)+mkSnaplet :: Initializer b v v -> Initializer b v (Snaplet v) mkSnaplet m = do     res <- m     cfg <- iGets _curConfig-    return $ Snaplet cfg res+    setInTop <- iGets masterReloader+    l <- getLens+    let modifier = setInTop  . set (cloneLens l . snapletValue)+    return $ Snaplet cfg modifier res+       ------------------------------------------------------------------------------@@ -325,10 +330,12 @@        -> Initializer b v a chroot rte l (Initializer m) = do     curState <- iGet+    let newSetter f = masterReloader curState (over (cloneLens l) f)     ((a,s), (Hook hook)) <- liftIO $ runWriterT $ LT.runLensT m id $         curState {           _handlers = [],-          _hFilter = id+          _hFilter = id,+          masterReloader = newSetter         }     let handler = chrootHandler l $ _hFilter s $ route $ _handlers s     iModify $ over handlers (++[(rte,handler)])@@ -443,17 +450,17 @@ -- | Builds an IO reload action for storage in the SnapletState. mkReloader :: FilePath            -> String-           -> MVar (Snaplet b)+           -> ((Snaplet b -> Snaplet b) -> IO ())            -> IORef (IO ())            -> Initializer b b (Snaplet b)            -> IO (Either Text Text)-mkReloader cwd env mvar cleanupRef i = do+mkReloader cwd env resetter cleanupRef i = do     join $ readIORef cleanupRef-    !res <- runInitializer' mvar env i cwd+    !res <- runInitializer' resetter env i cwd     either (return . Left) good res   where     good (b,is) = do-        _ <- swapMVar mvar b+        _ <- resetter (const b)         msgs <- readIORef $ _initMessages is         return $ Right msgs @@ -470,36 +477,47 @@   ------------------------------------------------------------------------------+-- | Lets you change a snaplet's initial state.  It's alomst like a reload,+-- except that it doesn't run the initializer.  It just modifies the result of+-- the initializer.  This can be used to let you define actions for reloading+-- individual snaplets.+modifyMaster :: v -> Handler b v ()+modifyMaster v = do+    modifier <- getsSnapletState _snapletModifier+    liftIO $ modifier v+++------------------------------------------------------------------------------ -- | Internal function for running Initializers.  If any exceptions were -- thrown by the initializer, this function catches them, runs any cleanup -- actions that had been registered, and returns an expanded error message -- containing the exception details as well as all messages generated by the -- initializer before the exception was thrown.-runInitializer :: MVar (Snaplet b)+runInitializer :: ((Snaplet b -> Snaplet b) -> IO ())                -> String                -> Initializer b b (Snaplet b)                -> IO (Either Text (Snaplet b, InitializerState b))-runInitializer mvar env b =-    getCurrentDirectory >>= runInitializer' mvar env b+runInitializer resetter env b =+    getCurrentDirectory >>= runInitializer' resetter env b   -------------------------------------------------------------------------------runInitializer' :: MVar (Snaplet b)+runInitializer' :: ((Snaplet b -> Snaplet b) -> IO ())                 -> String                 -> Initializer b b (Snaplet b)                 -> FilePath                 -> IO (Either Text (Snaplet b, InitializerState b))-runInitializer' mvar env b@(Initializer i) cwd = do+runInitializer' resetter env b@(Initializer i) cwd = do     cleanupRef <- newIORef (return ())+    let reloader_ = mkReloader cwd env resetter cleanupRef b     let builtinHandlers = [("/admin/reload", reloadSite)]-    let cfg = SnapletConfig [] cwd Nothing "" empty [] Nothing-                            (mkReloader cwd env mvar cleanupRef b)+    let cfg = SnapletConfig [] cwd Nothing "" empty [] Nothing reloader_     logRef <- newIORef ""      let body = runEitherT $ do             ((res, s), (Hook hook)) <- lift $ runWriterT $ LT.runLensT i id $                 InitializerState True cleanupRef builtinHandlers id cfg logRef-                                 env+                                 env resetter             res' <- hook res             right (res', s) @@ -528,7 +546,8 @@ runSnaplet :: Maybe String -> SnapletInit b b -> IO (Text, Snap (), IO ()) runSnaplet env (SnapletInit b) = do     snapletMVar <- newEmptyMVar-    eRes <- runInitializer snapletMVar (fromMaybe "devel" env) b+    let resetter f = modifyMVar_ snapletMVar (return . f)+    eRes <- runInitializer resetter (fromMaybe "devel" env) b     let go (siteSnaplet,is) = do         putMVar snapletMVar siteSnaplet         msgs <- liftIO $ readIORef $ _initMessages is@@ -574,10 +593,12 @@     createDirectoryIfMissing False "log"     let serve = simpleHttpServe conf -    liftIO $ hPutStrLn stderr $ T.unpack msgs+    when (loggingEnabled conf) $ liftIO $ hPutStrLn stderr $ T.unpack msgs     _ <- try $ serve $ site          :: IO (Either SomeException ())     doCleanup+  where+    loggingEnabled = not . (== Just False) . getVerbose   ------------------------------------------------------------------------------
src/Snap/Snaplet/Internal/Types.hs view
@@ -14,7 +14,6 @@ module Snap.Snaplet.Internal.Types where  import           Control.Applicative-import           Control.Comonad import           Control.Error import           Control.Lens import           Control.Monad.CatchIO hiding (Handler)@@ -27,7 +26,6 @@ import           Data.IORef import           Data.Monoid import           Data.Text (Text)-import           Data.Foldable (Foldable(..))  import           Snap.Core import qualified Snap.Snaplet.Internal.LensT as LT@@ -50,6 +48,10 @@         -- current handler.  Nothing during initialization and before route         -- dispatech.     , _reloader          :: IO (Either Text Text) -- might change+        -- ^ This is the universal reload action for the top-level site.  We+        -- can't update this in place to be a reloader for each individual+        -- snaplet because individual snaplets can't be reloaded in isolation+        -- without losing effects that subsequent hooks may have had.     }  makeLenses ''SnapletConfig@@ -58,7 +60,7 @@ ------------------------------------------------------------------------------ -- | Joins a reversed list of directories into a path. buildPath :: [ByteString] -> ByteString-buildPath ps = B.intercalate "/" $ reverse ps+buildPath ps = B.intercalate "/" $ filter (not . B.null) $ reverse ps   ------------------------------------------------------------------------------@@ -77,28 +79,35 @@ --   the snaplet's configuration, the snaplet's root directory on the --   filesystem, the snaplet's root URL, and so on. data Snaplet s = Snaplet-    { _snapletConfig :: SnapletConfig-    , _snapletValue  :: s+    { _snapletConfig   :: SnapletConfig+    , _snapletModifier :: s -> IO ()+        -- ^ See the _reloader comment for why we have to use this to reload+        -- single snaplets in isolation.  This action won't actually run the+        -- initializer at all.  It will only modify the existing state.  It is+        -- the responsibility of the snaplet author to avoid using this in+        -- situations where it will destroy data in its state that was created+        -- by subsequent hook actions.+    , _snapletValue    :: s     }  makeLenses ''Snaplet -instance Functor Snaplet where-  fmap f (Snaplet c a) = Snaplet c (f a)--instance Foldable Snaplet where-  foldMap f (Snaplet _ a) = f a--instance Traversable Snaplet where-  traverse f (Snaplet c a) = Snaplet c <$> f a--instance Comonad Snaplet where-  extract (Snaplet _ a) = a--#if !(MIN_VERSION_comonad(3,0,0))-instance Extend Snaplet where-#endif-  extend f w@(Snaplet c _) = Snaplet c (f w)+--instance Functor Snaplet where+--  fmap f (Snaplet c r a) = Snaplet c r (f a)+--+--instance Foldable Snaplet where+--  foldMap f (Snaplet _ _ a) = f a+--+--instance Traversable Snaplet where+--  traverse f (Snaplet c r a) = Snaplet c r <$> f a+--+--instance Comonad Snaplet where+--  extract (Snaplet _ _ a) = a+--+-- #if !(MIN_VERSION_comonad(3,0,0))+-- instance Extend Snaplet where+-- #endif+--   extend f w@(Snaplet c r _) = Snaplet c r (f w)  {- ------------------------------------------------------------------------------@@ -222,6 +231,18 @@   ------------------------------------------------------------------------------+-- | Constructs a url relative to the current snaplet.+snapletURL :: (Monad (m b v), MonadSnaplet m)+           => ByteString -> m b v ByteString+snapletURL suffix = do+    cfg <- getOpaqueConfig+    return $ buildPath (cleanSuffix : _scRouteContext cfg)+  where+    dropSlash = B.dropWhile (=='/')+    cleanSuffix = B.reverse $ dropSlash $ B.reverse $ dropSlash suffix+++------------------------------------------------------------------------------ -- | Snaplet infrastructure is available during runtime request processing -- through the Handler monad.  There aren't very many standalone functions to -- read about here, but this is deceptive.  The key is in the type class@@ -322,6 +343,19 @@   ------------------------------------------------------------------------------+-- | Pass if the request is not coming from localhost.+failIfNotLocal :: MonadSnap m => m b -> m b+failIfNotLocal m = do+    -- FIXME: this moves to auth once control-panel is done+    rip <- liftM rqRemoteAddr getRequest+    if not $ elem rip [ "127.0.0.1"+                      , "localhost"+                      , "::1" ]+      then pass+      else m+++------------------------------------------------------------------------------ -- | Handler that reloads the site. reloadSite :: Handler b v () reloadSite = failIfNotLocal $ do@@ -335,14 +369,6 @@     good msg = do         writeText msg         writeText $ "Site successfully reloaded.\n"-    failIfNotLocal m = do-        -- FIXME: this moves to auth once control-panel is done-        rip <- liftM rqRemoteAddr getRequest-        if not $ elem rip [ "127.0.0.1"-                          , "localhost"-                          , "::1" ]-          then pass-          else m   ------------------------------------------------------------------------------@@ -384,6 +410,9 @@         -- whatever snaplet is currently being constructed.     , _initMessages    :: IORef Text     , _environment     :: String+    , masterReloader   :: (Snaplet b -> Snaplet b) -> IO ()+        -- ^ We can't just hae a simple MVar here because MVars can't be+        -- chrooted.     }  @@ -422,15 +451,5 @@ -- | Opaque newtype which gives us compile-time guarantees that the user is -- using makeSnaplet and either nestSnaplet or embedSnaplet correctly. newtype SnapletInit b v = SnapletInit (Initializer b v (Snaplet v))------------------------------------------------------------------------------------ | Information needed to reload a site.  Instead of having snaplets define--- their own reload actions, we store the original site initializer and use it--- instead.-data ReloadInfo b = ReloadInfo-    { riRef     :: IORef (Snaplet b)-    , riAction  :: Initializer b b b-    }  
src/Snap/Snaplet/Session/Backends/CookieSession.hs view
@@ -4,8 +4,8 @@ {-# LANGUAGE OverloadedStrings          #-}  module Snap.Snaplet.Session.Backends.CookieSession-  ( initCookieSessionManager-  ) where+    ( initCookieSessionManager+    ) where  ------------------------------------------------------------------------------ import           Control.Applicative@@ -14,10 +14,10 @@ import           Data.Generics import           Data.HashMap.Strict                 (HashMap) import qualified Data.HashMap.Strict                 as HM-import           Data.Hashable                       (Hashable) import           Data.Serialize                      (Serialize) import qualified Data.Serialize                      as S import           Data.Text                           (Text)+import           Data.Text.Encoding import           Snap.Core                           (Snap) import           Web.ClientSession ------------------------------------------------------------------------------@@ -45,13 +45,20 @@  ------------------------------------------------------------------------------ instance Serialize CookieSession where-    put (CookieSession a b) = S.put (a,b)-    get                     = uncurry CookieSession <$> S.get+    put (CookieSession a b) =+        S.put (encodeUtf8 a, map encodeTuple $ HM.toList b)+    get                     =+        let unpack (a,b) = CookieSession (decodeUtf8 a)+                                         (HM.fromList $ map decodeTuple b)+        in  unpack <$> S.get -instance (Serialize k, Serialize v, Hashable k,-          Eq k) => Serialize (HashMap k v) where-    put = S.put . HM.toList-    get = HM.fromList <$> S.get++encodeTuple :: (Text, Text) -> (ByteString, ByteString)+encodeTuple (a,b) = (encodeUtf8 a, encodeUtf8 b)+++decodeTuple :: (ByteString, ByteString) -> (Text, Text)+decodeTuple (a,b) = (decodeUtf8 a, decodeUtf8 b)   ------------------------------------------------------------------------------
src/Snap/Snaplet/Session/Common.hs view
@@ -14,8 +14,6 @@ import           Control.Applicative import           Control.Concurrent import           Control.Monad-import           Data.Serialize-import qualified Data.Serialize as S import           Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import qualified Data.Text.Encoding as T@@ -58,9 +56,4 @@ mkCSRFToken :: RNG -> IO Text mkCSRFToken rng = T.decodeUtf8 <$> randomToken 40 rng ---------------------------------------------------------------------------------instance Serialize Text where-    put = S.put . T.encodeUtf8-    get = T.decodeUtf8 <$> S.get 
src/Snap/Snaplet/Session/SecureCookie.hs view
@@ -28,9 +28,9 @@  ------------------------------------------------------------------------------ -- | Serialize UTCTime-instance Serialize UTCTime where-    put t = put (round (utcTimeToPOSIXSeconds t) :: Integer)-    get   = posixSecondsToUTCTime . fromInteger <$> get+--instance Serialize UTCTime where+--    put t = put (round (utcTimeToPOSIXSeconds t) :: Integer)+--    get   = posixSecondsToUTCTime . fromInteger <$> get   ------------------------------------------------------------------------------@@ -54,7 +54,7 @@     case val' of       Nothing -> return Nothing       Just (ts, t) -> do-          to <- checkTimeout timeout ts+          to <- checkTimeout timeout $ posixSecondsToUTCTime $ fromInteger ts           return $ case to of             True -> Nothing             False -> Just t@@ -70,8 +70,9 @@                 -> m () setSecureCookie name key to val = do     t <- liftIO getCurrentTime+    let seconds = round (utcTimeToPOSIXSeconds t) :: Integer     let expire = to >>= Just . flip addUTCTime t . fromIntegral-    val' <- liftIO . encryptIO key . encode $ (t, val)+    val' <- liftIO . encryptIO key . encode $ (seconds, val)     let nc = Cookie name val' expire Nothing (Just "/") False True     modifyResponse $ addResponseCookie nc 
src/Snap/Snaplet/Test.hs view
@@ -102,6 +102,7 @@            => SnapletInit b b            -> m (Either Text (Snaplet b, InitializerState b)) getSnaplet (SnapletInit initializer) = liftIO $ do-        mvar <- newEmptyMVar-        runInitializer mvar "" initializer+    mvar <- newEmptyMVar+    let resetter f = modifyMVar_ mvar (return . f)+    runInitializer resetter "" initializer 
test/snap-testsuite.cabal view
@@ -15,12 +15,14 @@     Glob                       >= 0.5      && < 0.8,     HUnit                      >= 1.2      && < 2,     QuickCheck                 >= 2.3.0.2,-    http-conduit               >= 1.7      && < 1.9,-    http-types                 >= 0.6      && < 0.8,+    blaze-builder              >= 0.3      && < 0.4,+    http-streams               >= 0.4.0.1  && < 0.5,     process                    == 1.*,+    smallcheck                 >= 0.6      && < 0.7,     test-framework             >= 0.6      && < 0.7,     test-framework-hunit       >= 0.2.7    && < 0.3,     test-framework-quickcheck2 >= 0.2.12.1 && < 0.3,+    test-framework-smallcheck  >= 0.1      && < 0.2,     unix                       >= 2.2.0.0  && < 2.7,      MonadCatchIO-transformers  >= 0.2      && < 0.4,@@ -39,17 +41,19 @@     filepath                   >= 1.1      && < 1.4,     -- Blacklist bad versions of hashable     hashable                  (>= 1.1 && < 1.2) || (>= 1.2.0.6 && <1.3),-    heist                      >= 0.10     && < 0.12,+    heist                      >= 0.12     && < 0.13,     logict                     >= 0.4.2    && < 0.6,     mtl                        >  2.0      && < 2.2,     mwc-random                 >= 0.8      && < 0.13,     pwstore-fast               >= 2.2      && < 2.4,     regex-posix                >= 0.95     && < 1,-    snap-core                  >= 0.9      && < 0.10,-    snap-server                >= 0.9      && < 0.10,+    snap-core                  >= 0.9      && < 0.11,+    snap-server                >= 0.9      && < 0.11,     stm                        >= 2.2      && < 2.5,     syb                        >= 0.1      && < 0.5,     text                       >= 0.11     && < 0.12,+    -- Without the tagged dependency we reach backtrack limits+    tagged                     < 0.5,     time                       >= 1.1      && < 1.5,     transformers               >= 0.2      && < 0.4,     unordered-containers       >= 0.1.4    && < 0.3,@@ -111,16 +115,18 @@     filepath                   >= 1.1      && < 1.4,     -- Blacklist bad versions of hashable     hashable                  (>= 1.1 && < 1.2) || (>= 1.2.0.6 && <1.3),-    heist                      >= 0.10     && < 0.12,+    heist                      >= 0.12     && < 0.13,     logict                     >= 0.4.2    && < 0.6,     mtl                        >  2.0      && < 2.2,     mwc-random                 >= 0.8      && < 0.13,     pwstore-fast               >= 2.2      && < 2.4,     regex-posix                >= 0.95     && < 1,-    snap-core                  >= 0.9      && < 0.10,-    snap-server                >= 0.9      && < 0.10,+    snap-core                  >= 0.9      && < 0.11,+    snap-server                >= 0.9      && < 0.11,     stm                        >= 2.2      && < 2.5,     syb                        >= 0.1      && < 0.5,+    -- Without the tagged dependency we reach backtrack limits+    tagged                     < 0.5,     text                       >= 0.11     && < 0.12,     time                       >= 1.1      && < 1.5,     transformers               >= 0.2      && < 0.4,@@ -168,12 +174,13 @@     Glob                       >= 0.5      && < 0.8,     HUnit                      >= 1.2      && < 2,     QuickCheck                 >= 2.3.0.2,-    http-conduit               >= 1.7      && < 1.9,-    http-types                 >= 0.6      && < 0.8,+    http-streams               >= 0.4.0.1  && < 0.5,     process                    == 1.*,+    smallcheck                 >= 0.6      && < 0.7,     test-framework             >= 0.6      && < 0.7,     test-framework-hunit       >= 0.2.7    && < 0.3,     test-framework-quickcheck2 >= 0.2.12.1 && < 0.3,+    test-framework-smallcheck  >= 0.1      && < 0.2,     unix                       >= 2.2.0.0  && < 2.7,      MonadCatchIO-transformers  >= 0.2      && < 0.4,@@ -192,16 +199,18 @@     filepath                   >= 1.1      && < 1.4,     -- Blacklist bad versions of hashable     hashable                  (>= 1.1 && < 1.2) || (>= 1.2.0.6 && <1.3),-    heist                      >= 0.10     && < 0.12,+    heist                      >= 0.12     && < 0.13,     logict                     >= 0.4.2    && < 0.6,     mtl                        >  2.0      && < 2.2,     mwc-random                 >= 0.8      && < 0.13,     pwstore-fast               >= 2.2      && < 2.4,     regex-posix                >= 0.95     && < 1,-    snap-core                  >= 0.9      && < 0.10,-    snap-server                >= 0.9      && < 0.10,+    snap-core                  >= 0.9      && < 0.11,+    snap-server                >= 0.9      && < 0.11,     stm                        >= 2.2      && < 2.5,     syb                        >= 0.1      && < 0.5,+    -- Without the tagged dependency we reach backtrack limits+    tagged                     < 0.5,     text                       >= 0.11     && < 0.12,     time                       >= 1.1      && < 1.5,     transformers               >= 0.2      && < 0.4,
test/suite/Blackbox/App.hs view
@@ -15,6 +15,7 @@ import Control.Lens import Control.Monad.Trans import Data.Maybe+import Data.Monoid import qualified Data.Text as T import qualified Data.Text.Encoding as T import Data.Configurator@@ -25,6 +26,7 @@ import Snap.Snaplet import Snap.Snaplet.Heist import qualified Snap.Snaplet.HeistNoClass as HNC+import Heist import Heist.Interpreted  ------------------------------------------------------------------------------@@ -51,10 +53,9 @@           initCookieSessionManager "sitekey.txt" "_session" (Just (30 * 60))     ns <- embedSnaplet "embed" embedded embeddedInit     _lens <- getLens-    addSplices-        [("appsplice", textSplice "contents of the app splice")]-    HNC.addSplices heist-        [("appconfig", shConfigSplice _lens)]+    addConfig hs $ mempty+        { hcInterpretedSplices = [("appsplice", textSplice "contents of the app splice")+                                 ,("appconfig", shConfigSplice _lens)] }     addRoutes [ ("/hello", writeText "hello world")               , ("/routeWithSplice", routeWithSplice)               , ("/routeWithConfig", routeWithConfig)
test/suite/Blackbox/FooSnaplet.hs view
@@ -7,10 +7,12 @@ import Control.Monad.State import Data.Configurator import Data.Maybe+import Data.Monoid import qualified Data.Text as T import Snap.Snaplet import Snap.Snaplet.Heist import Snap.Core+import Heist import Heist.Interpreted  import Blackbox.Common@@ -22,13 +24,14 @@     (Just $ return "../foosnaplet") $ do     config <- getSnapletUserConfig     addTemplates h ""-    addSplices-        [("foosplice", textSplice "contents of the foo splice")]     rootUrl <- getSnapletRootURL     fp <- getSnapletFilePath     name <- getSnapletName     _lens <- getLens-    addSplices [("fooconfig", shConfigSplice _lens)]+    addConfig h $ mempty+        { hcInterpretedSplices = [("foosplice", textSplice "contents of the foo splice")+                                 ,("fooconfig", shConfigSplice _lens)]+        }     addRoutes [("fooConfig", liftIO (lookup config "fooSnapletField") >>= writeLBS . fromJust)               ,("fooRootUrl", writeBS rootUrl)               ,("fooSnapletName", writeText $ fromMaybe "empty snaplet name" name)
test/suite/Blackbox/Tests.hs view
@@ -8,16 +8,18 @@   ) where  ------------------------------------------------------------------------------+import           Blaze.ByteString.Builder       (Builder)+import qualified Blaze.ByteString.Builder       as Builder import           Control.Exception              (catch, throwIO) import           Control.Monad import           Control.Monad.Trans import qualified Data.ByteString.Char8          as S import qualified Data.ByteString.Lazy.Char8     as L+import           Data.Monoid import           Data.Text.Lazy                 (Text) import qualified Data.Text.Lazy                 as T import qualified Data.Text.Lazy.Encoding        as T-import qualified Network.HTTP.Conduit           as HTTP-import           Network.HTTP.Types             (Status(..))+import           Network.Http.Client import           Prelude                        hiding (catch) import           System.Directory import           System.FilePath@@ -108,8 +110,8 @@ ------------------------------------------------------------------------------ requestTest' :: String -> Text -> IO () requestTest' url desired = do-    actual <- HTTP.simpleHttp $ testServerUrl ++ url-    assertEqual url desired (T.decodeUtf8 actual)+    actual <- get (S.pack $ testServerUrl ++ url) concatHandler+    assertEqual url desired (T.decodeUtf8 $ L.fromChunks [actual])   ------------------------------------------------------------------------------@@ -122,13 +124,11 @@ requestExpectingError' :: String -> Int -> Text -> IO () requestExpectingError' url status desired = do     let fullUrl = testServerUrl ++ url-    req <- HTTP.parseUrl fullUrl-    let req' = req { HTTP.checkStatus = \_ _ -> Nothing }-    resp <- liftIO $ HTTP.withManager $ HTTP.httpLbs req'-    let b = HTTP.responseBody resp-        s = HTTP.responseStatus resp-    assertEqual ("Status code: "++fullUrl) status (statusCode s)-    assertEqual fullUrl desired (T.decodeUtf8 b)+    get (S.pack fullUrl) $ \resp is -> do+      assertEqual ("Status code: "++fullUrl) status+                  (getStatusCode resp)+      res <- concatHandler resp is+      assertEqual fullUrl desired (T.decodeUtf8 $ L.fromChunks [res])   ------------------------------------------------------------------------------@@ -147,7 +147,8 @@  ------------------------------------------------------------------------------ grab :: MonadIO m => String -> m L.ByteString-grab path = liftIO $ HTTP.simpleHttp $ testServerUri ++ path+grab path = liftIO $ liftM (L.fromChunks . (:[])) $+  get (S.pack $ testServerUri ++ path) concatHandler   ------------------------------------------------------------------------------@@ -229,16 +230,11 @@  ------------------------------------------------------------------------------ expect404 :: String -> IO ()-expect404 url = action `catch` h-  where-    action = do-        HTTP.simpleHttp $ testServerUrl ++ url-        assertFailure "expected 404"--    h e@(HTTP.StatusCodeException (Status c _) _)-      | c == 404  = return ()-      | otherwise = throwIO e-    h e           = throwIO e+expect404 url = do+    get (S.pack $ testServerUrl ++ url) $ \resp i -> do+        case getStatusCode resp of+          404 -> return ()+          _   -> assertFailure "expected 404"   ------------------------------------------------------------------------------
test/suite/SafeCWD.hs view
@@ -11,7 +11,9 @@  sem :: QSem sem = unsafePerformIO $ newQSem 1+{-# NOINLINE sem #-} + inDir :: Bool -> FilePath -> IO a -> IO a inDir startClean dir action = bracket before after (const action)   where@@ -25,6 +27,7 @@     after cwd = do         setCurrentDirectory cwd         signalQSem sem+  removeDirectoryRecursiveSafe p =     doesDirectoryExist p >>= flip when (removeDirectoryRecursive p)
test/suite/Snap/Snaplet/Internal/Tests.hs view
@@ -11,13 +11,16 @@ import           Control.Monad import           Control.Monad.Trans import           Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as B import           Data.List-import           Data.Text+import           Data.Text (Text) import           Prelude hiding (catch, (.)) import           System.Directory import           Test.Framework import           Test.Framework.Providers.HUnit+import           Test.Framework.Providers.SmallCheck import           Test.HUnit hiding (Test, path)+import           Test.SmallCheck ------------------------------------------------------------------------------ import           Snap.Snaplet.Internal.Initializer import           Snap.Snaplet.Internal.Types@@ -120,5 +123,13 @@ tests :: Test tests = testGroup "Snap.Snaplet.Internal"     [ testCase "initializer tests" initTest+    , testProperty "buildPath generates no double slashes" doubleSlashes     ]++--doubleSlashes :: Monad m => [String] -> Property m+doubleSlashes arrStr = noSlashes ==> not (B.isInfixOf "//" $ buildPath arr)+  where+    arr = map B.pack arrStr+    noSlashes = not $ or $ map (B.elem '/') arr+ 
test/suite/TestSuite.hs view
@@ -9,7 +9,7 @@ import           Control.Monad import qualified Data.ByteString.Lazy.Char8 as L import qualified Data.ByteString.Char8 as S-import qualified Network.HTTP.Conduit    as HTTP+import           Network.Http.Client import           Prelude hiding (catch) import           Snap.Http.Server.Config import           Snap.Snaplet@@ -102,12 +102,12 @@   where     go = testGeneratedProject "barebonesTest"                               "barebones"-                              ""+                              "--force-reinstalls"                               port                               testIt     port = 9990 :: Int     testIt = do-        body <- HTTP.simpleHttp $ "http://127.0.0.1:"++(show port)+        body <- get (S.pack $ "http://127.0.0.1:"++(show port)) concatHandler         assertEqual "server not up" "hello world" body  @@ -117,13 +117,12 @@   where     go = testGeneratedProject "defaultTest"                               ""-                              ""+                              "--force-reinstalls"                               port                               testIt     port = 9991 :: Int     testIt = do-        body <- liftM (S.concat . L.toChunks) $-                HTTP.simpleHttp $ "http://127.0.0.1:"++(show port)+        body <- get (S.pack $ "http://127.0.0.1:"++(show port)) concatHandler         assertBool "response contains phrase 'Snap Example App Login'"                    $ "Snap Example App Login" `S.isInfixOf` body @@ -134,12 +133,12 @@   where     go = testGeneratedProject "tutorialTest"                               "tutorial"-                              ""+                              "--force-reinstalls"                               port                               testIt     port = 9992 :: Int     testIt = do-        body <- HTTP.simpleHttp $ "http://127.0.0.1:"++(show port)++"/hello"+        body <- get (S.pack $ "http://127.0.0.1:"++(show port)++"/hello") concatHandler         assertEqual "server not up" "hello world" body