Spock 0.7.3.0 → 0.7.4.0
raw patch · 10 files changed
+95/−125 lines, 10 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Web.Spock.Safe: spockApp :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Application
- Web.Spock.Safe: spockMiddleware :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Middleware
- Web.Spock.Simple: spockApp :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Application
- Web.Spock.Simple: spockMiddleware :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Middleware
+ Web.Spock.Shared: runSpock :: Port -> IO Middleware -> IO ()
+ Web.Spock.Shared: spockAsApp :: IO Middleware -> IO Application
- Web.Spock.Safe: spock :: Int -> SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO ()
+ Web.Spock.Safe: spock :: SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO Middleware
- Web.Spock.Safe: spockT :: MonadIO m => Port -> (forall a. m a -> IO a) -> SpockT m () -> IO ()
+ Web.Spock.Safe: spockT :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Middleware
- Web.Spock.Simple: spock :: Int -> SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO ()
+ Web.Spock.Simple: spock :: SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO Middleware
- Web.Spock.Simple: spockT :: MonadIO m => Port -> (forall a. m a -> IO a) -> SpockT m () -> IO ()
+ Web.Spock.Simple: spockT :: MonadIO m => (forall a. m a -> IO a) -> SpockT m () -> IO Middleware
Files
- Spock.cabal +1/−2
- src/Web/Spock/Internal/Core.hs +44/−7
- src/Web/Spock/Internal/Types.hs +1/−1
- src/Web/Spock/Internal/Wire.hs +5/−9
- src/Web/Spock/Internal/Wrapper.hs +0/−50
- src/Web/Spock/Safe.hs +11/−26
- src/Web/Spock/Shared.hs +20/−2
- src/Web/Spock/Simple.hs +11/−26
- test/Web/Spock/SafeSpec.hs +1/−1
- test/Web/Spock/SimpleSpec.hs +1/−1
Spock.cabal view
@@ -1,5 +1,5 @@ name: Spock-version: 0.7.3.0+version: 0.7.4.0 synopsis: Another Haskell web framework for rapid development description: This toolbox provides everything you need to get a quick start into web hacking with haskell: fast routing, middleware, json, blaze, sessions, cookies, database helper, csrf-protection Homepage: https://github.com/agrafix/Spock@@ -25,7 +25,6 @@ Web.Spock.Internal.Util, Web.Spock.Internal.Core, Web.Spock.Internal.CoreAction,- Web.Spock.Internal.Wrapper, Web.Spock.Internal.Wire build-depends: aeson >= 0.6.2.1 && <0.9, base >= 4 && < 5,
src/Web/Spock/Internal/Core.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE TypeFamilies #-} module Web.Spock.Internal.Core ( SpockAllT+ , spockAll , spockAllT , middleware , hookRoute@@ -13,22 +14,58 @@ ) where +import Web.Spock.Internal.SessionManager+import Web.Spock.Internal.Types import Web.Spock.Internal.Wire import Control.Monad.Error+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Resource+import Data.Pool import Prelude hiding (head) import Web.Routing.AbstractRouter-import qualified Network.Wai.Handler.Warp as Warp+import qualified Network.Wai as Wai +-- | Run a spock application using the warp server, a given db storageLayer and an initial state.+-- Spock works with database libraries that already implement connection pooling and+-- with those that don't come with it out of the box. For more see the 'PoolOrConn' type.+spockAll :: forall r conn sess st.+ ( AbstractRouter r+ , RouteAppliedAction r ~ ActionT (WebStateM conn sess st) ()+ )+ => r+ -> SessionCfg sess+ -> PoolOrConn conn+ -> st+ -> SpockAllM r conn sess st ()+ -> IO Wai.Middleware+spockAll regIf sessionCfg poolOrConn initialState defs =+ do sessionMgr <- createSessionManager sessionCfg+ connectionPool <-+ case poolOrConn of+ PCPool p ->+ return p+ PCConn cb ->+ let pc = cb_poolConfiguration cb+ in createPool (cb_createConn cb) (cb_destroyConn cb)+ (pc_stripes pc) (pc_keepOpenTime pc)+ (pc_resPerStripe pc)+ let internalState =+ WebState+ { web_dbConn = connectionPool+ , web_sessionMgr = sessionMgr+ , web_state = initialState+ }+ spockAllT regIf (\m -> runResourceT $ runReaderT (runWebStateM m) internalState) $+ do defs+ middleware (sm_middleware sessionMgr)+ -- | Run a raw spock server on a defined port. If you don't need -- a custom base monad you can just supply 'id' as lift function. spockAllT :: (MonadIO m, AbstractRouter r, RouteAppliedAction r ~ ActionT m ()) => r- -> Warp.Port -> (forall a. m a -> IO a) -> SpockAllT r m ()- -> IO ()-spockAllT registryIf port liftSpock routeDefs =- do spockApp <- buildApp registryIf liftSpock routeDefs- putStrLn $ "Spock is up and running on port " ++ show port- Warp.run port spockApp+ -> IO Wai.Middleware+spockAllT registryIf liftSpock routeDefs =+ buildMiddleware registryIf liftSpock routeDefs
src/Web/Spock/Internal/Types.hs view
@@ -6,8 +6,8 @@ {-# LANGUAGE ExistentialQuantification #-} module Web.Spock.Internal.Types where -import Web.Spock.Internal.Core import Web.Spock.Internal.CoreAction+import Web.Spock.Internal.Wire import Control.Applicative import Control.Concurrent.STM
src/Web/Spock/Internal/Wire.hs view
@@ -135,14 +135,10 @@ type SpockAllT r m a = RegistryT r Wai.Middleware StdMethod m a -buildApp :: forall m r. (MonadIO m, AbstractRouter r, RouteAppliedAction r ~ ActionT m ())- => r- -> (forall a. m a -> IO a)- -> SpockAllT r m ()- -> IO Wai.Application-buildApp registryIf registryLift spockActions =- do mw <- buildMiddleware registryIf registryLift spockActions- return (mw fallbackApp)+middlewareToApp :: Wai.Middleware+ -> Wai.Application+middlewareToApp mw =+ mw fallbackApp where fallbackApp :: Wai.Application fallbackApp _ respond =@@ -152,7 +148,7 @@ => r -> (forall a. m a -> IO a) -> SpockAllT r m ()- -> IO (Wai.Application -> Wai.Application)+ -> IO Wai.Middleware buildMiddleware registryIf registryLift spockActions = do (_, getMatchingRoutes, middlewares) <- registryLift $ runRegistry registryIf spockActions
− src/Web/Spock/Internal/Wrapper.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE DoAndIfThenElse #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE TypeFamilies #-}-module Web.Spock.Internal.Wrapper where--import Web.Spock.Internal.Core-import Web.Spock.Internal.Wire-import Web.Spock.Internal.SessionManager-import Web.Spock.Internal.Types--import Control.Monad.Trans.Reader-import Control.Monad.Trans.Resource-import Data.Pool-import Web.Routing.AbstractRouter---- | Run a spock application using the warp server, a given db storageLayer and an initial state.--- Spock works with database libraries that already implement connection pooling and--- with those that don't come with it out of the box. For more see the 'PoolOrConn' type.-spockAll :: forall r conn sess st.- ( AbstractRouter r- , RouteAppliedAction r ~ ActionT (WebStateM conn sess st) ()- )- => r- -> Int- -> SessionCfg sess- -> PoolOrConn conn- -> st- -> SpockAllM r conn sess st ()- -> IO ()-spockAll regIf port sessionCfg poolOrConn initialState defs =- do sessionMgr <- createSessionManager sessionCfg- connectionPool <-- case poolOrConn of- PCPool p ->- return p- PCConn cb ->- let pc = cb_poolConfiguration cb- in createPool (cb_createConn cb) (cb_destroyConn cb)- (pc_stripes pc) (pc_keepOpenTime pc)- (pc_resPerStripe pc)- let internalState =- WebState- { web_dbConn = connectionPool- , web_sessionMgr = sessionMgr- , web_state = initialState- }- spockAllT regIf port (\m -> runResourceT $ runReaderT (runWebStateM m) internalState) $- do defs- middleware (sm_middleware sessionMgr)
src/Web/Spock/Safe.hs view
@@ -11,7 +11,6 @@ ( -- * Spock's core spock, SpockM, SpockAction , spockT, SpockT, ActionT- , spockApp -- * Defining routes , Path, root, var, static, (</>) -- * Rendering routes@@ -22,8 +21,6 @@ , Http.StdMethod (..) -- * Adding Wai.Middleware , middleware- -- * Using Spock as middleware- , spockMiddleware -- * Safe actions , SafeAction (..) , safeActionPath@@ -35,8 +32,6 @@ import Web.Spock.Shared import Web.Spock.Internal.CoreAction import Web.Spock.Internal.Types-import Web.Spock.Internal.Wrapper-import qualified Web.Spock.Internal.Wire as W import qualified Web.Spock.Internal.Core as C import Control.Applicative@@ -49,7 +44,6 @@ import qualified Data.Text as T import qualified Network.HTTP.Types as Http import qualified Network.Wai as Wai-import qualified Network.Wai.Handler.Warp as Warp type SpockM conn sess st a = SpockT (WebStateM conn sess st) a @@ -60,35 +54,26 @@ instance MonadTrans SpockT where lift = SpockT . lift --- | Run a spock application using the warp server, a given db storageLayer and an initial state.+-- | Create a spock application using a given db storageLayer and an initial state. -- Spock works with database libraries that already implement connection pooling and -- with those that don't come with it out of the box. For more see the 'PoolOrConn' type.-spock :: Int -> SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO ()-spock port sessCfg poolOrConn initSt spockAppl =- spockAll SafeRouter port sessCfg poolOrConn initSt (runSpockT spockAppl')+-- Use @runSpock@ to run the app or @spockAsApp@ to create a @Wai.Application@+spock :: SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO Wai.Middleware+spock sessCfg poolOrConn initSt spockAppl =+ C.spockAll SafeRouter sessCfg poolOrConn initSt (runSpockT spockAppl') where spockAppl' = do hookSafeActions spockAppl --- | Run a raw spock application with custom underlying monad+-- | Create a raw spock application with custom underlying monad+-- Use @runSpock@ to run the app or @spockAsApp@ to create a @Wai.Application@ spockT :: (MonadIO m)- => Warp.Port- -> (forall a. m a -> IO a)+ => (forall a. m a -> IO a) -> SpockT m ()- -> IO ()-spockT port liftFun (SpockT app) =- C.spockAllT SafeRouter port liftFun app---- | Convert a Spock-App to a wai-application-spockApp :: (MonadIO m) => (forall a. m a -> IO a) -> SpockT m () -> IO Wai.Application-spockApp liftFun (SpockT app) =- W.buildApp SafeRouter liftFun app---- | Convert a Spock-App to a wai-middleware-spockMiddleware :: (MonadIO m) => (forall a. m a -> IO a) -> SpockT m () -> IO Wai.Middleware-spockMiddleware liftFun (SpockT app) =- W.buildMiddleware SafeRouter liftFun app+ -> IO Wai.Middleware+spockT liftFun (SpockT app) =+ C.spockAllT SafeRouter liftFun app -- | Specify an action that will be run when the HTTP verb 'GET' and the given route match get :: MonadIO m => Path xs -> HVectElim xs (ActionT m ()) -> SpockT m ()
@@ -8,8 +8,10 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE DataKinds #-} module Web.Spock.Shared- (-- * Handeling requests- request, header, cookie, body, jsonBody, jsonBody', files, UploadedFile (..)+ (-- * Helpers for running Spock+ runSpock, spockAsApp+ -- * Handeling requests+ , request, header, cookie, body, jsonBody, jsonBody', files, UploadedFile (..) , params, param, param' -- * Sending responses , setStatus, setHeader, redirect, jumpNext, setCookie, setCookie', bytes, lazyBytes@@ -37,6 +39,22 @@ import Web.Spock.Internal.SessionManager import Web.Spock.Internal.Types import Web.Spock.Internal.CoreAction+import Control.Monad+import qualified Web.Spock.Internal.Wire as W+import qualified Network.Wai as Wai+import qualified Network.Wai.Handler.Warp as Warp++-- | Run a Spock application. Basically just a wrapper aroung @Warp.run@.+runSpock :: Warp.Port -> IO Wai.Middleware -> IO ()+runSpock port mw =+ do putStrLn ("Spock is running on port " ++ show port)+ app <- spockAsApp mw+ Warp.run port app++-- | Convert a middleware to an application. All failing requests will+-- result in a 404 page+spockAsApp :: IO Wai.Middleware -> IO Wai.Application+spockAsApp = liftM W.middlewareToApp -- | Get the current users sessionId. Note that this ID should only be -- shown to it's owner as otherwise sessions can be hijacked.
src/Web/Spock/Simple.hs view
@@ -10,7 +10,6 @@ ( -- * Spock's core spock, SpockM, SpockAction , spockT, SpockT, ActionT- , spockApp -- * Defining routes , SpockRoute, (<#>) -- * Hooking routes@@ -19,8 +18,6 @@ , Http.StdMethod (..) -- * Adding Wai.Middleware , middleware- -- * Using Spock as middleware- , spockMiddleware -- * Safe actions , SafeAction (..) , safeActionPath@@ -31,8 +28,6 @@ import Web.Spock.Shared import Web.Spock.Internal.CoreAction import Web.Spock.Internal.Types-import Web.Spock.Internal.Wrapper-import qualified Web.Spock.Internal.Wire as W import qualified Web.Spock.Internal.Core as C import Control.Applicative@@ -45,7 +40,6 @@ import qualified Data.Text as T import qualified Network.HTTP.Types as Http import qualified Network.Wai as Wai-import qualified Network.Wai.Handler.Warp as Warp type SpockM conn sess st a = SpockT (WebStateM conn sess st) a @@ -60,35 +54,26 @@ = SpockRoute { _unSpockRoute :: T.Text } deriving (Eq, Ord, Show, Read, IsString) --- | Run a spock application using the warp server, a given db storageLayer and an initial state.+-- | Create a spock application using a given db storageLayer and an initial state. -- Spock works with database libraries that already implement connection pooling and -- with those that don't come with it out of the box. For more see the 'PoolOrConn' type.-spock :: Int -> SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO ()-spock port sessCfg poolOrConn initSt spockAppl =- spockAll TextRouter port sessCfg poolOrConn initSt (runSpockT spockAppl')+-- Use @runSpock@ to run the app or @spockAsApp@ to create a @Wai.Application@+spock :: SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO Wai.Middleware+spock sessCfg poolOrConn initSt spockAppl =+ C.spockAll TextRouter sessCfg poolOrConn initSt (runSpockT spockAppl') where spockAppl' = do hookSafeActions spockAppl --- | Run a raw spock application with custom underlying monad+-- | Create a raw spock application with custom underlying monad+-- Use @runSpock@ to run the app or @spockAsApp@ to create a @Wai.Application@ spockT :: (MonadIO m)- => Warp.Port- -> (forall a. m a -> IO a)+ => (forall a. m a -> IO a) -> SpockT m ()- -> IO ()-spockT port liftFun (SpockT app) =- C.spockAllT TextRouter port liftFun app---- | Convert a Spock-App to a wai-application-spockApp :: (MonadIO m) => (forall a. m a -> IO a) -> SpockT m () -> IO Wai.Application-spockApp liftFun (SpockT app) =- W.buildApp TextRouter liftFun app---- | Convert a Spock-App to a wai-middleware-spockMiddleware :: (MonadIO m) => (forall a. m a -> IO a) -> SpockT m () -> IO Wai.Middleware-spockMiddleware liftFun (SpockT app) =- W.buildMiddleware TextRouter liftFun app+ -> IO Wai.Middleware+spockT liftFun (SpockT app) =+ C.spockAllT TextRouter liftFun app -- | Combine two route components safely -- "/foo" <#> "/bar" ===> "/foo/bar"
test/Web/Spock/SafeSpec.hs view
@@ -28,4 +28,4 @@ hookAny GET $ text . T.intercalate "/" spec :: Spec-spec = describe "SafeRouting" $ frameworkSpec (spockApp id app)+spec = describe "SafeRouting" $ frameworkSpec (spockAsApp $ spockT id app)
test/Web/Spock/SimpleSpec.hs view
@@ -29,4 +29,4 @@ hookAny GET $ text . T.intercalate "/" spec :: Spec-spec = describe "SimpleRouting" $ frameworkSpec (spockApp id app)+spec = describe "SimpleRouting" $ frameworkSpec (spockAsApp $ spockT id app)