This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "snap-server".

The branch, snapt has been created
        at  33f70b908c7ecf892f4abb2f3b0ceac062dd1639 (commit)

- Log -----------------------------------------------------------------
commit 33f70b908c7ecf892f4abb2f3b0ceac062dd1639
Author: Mighty Byte <[email protected]>
Date:   Wed Dec 8 12:43:52 2010 -0500

    Working on porting to SnapT.  To finish it, the server functions need 
another parameter along the lines of "(SnapT m a -> SnapT IO a)" or "(m a -> IO 
a)".

diff --git a/src/Snap/Http/Server.hs b/src/Snap/Http/Server.hs
index 8250161..976dcdf 100644
--- a/src/Snap/Http/Server.hs
+++ b/src/Snap/Http/Server.hs
@@ -21,6 +21,7 @@ module Snap.Http.Server
 
 import           Control.Monad
 import           Control.Monad.CatchIO
+import           Control.Monad.Trans
 import           Data.ByteString (ByteString)
 import           Data.Char
 import           Data.List
@@ -47,9 +48,9 @@ snapServerVersion = Int.snapServerVersion
 -- settings from the given config; error handling and compression are ignored.
 -- This function never returns; to shut down the HTTP server, kill the
 -- controlling thread.
-simpleHttpServe :: MonadSnap m => Config m a -> Snap () -> IO ()
+simpleHttpServe :: MonadIO m => Config (SnapT m) a -> SnapT m () -> m ()
 simpleHttpServe config handler = do
-    setUnicodeLocale $ fromJust $ getLocale conf
+    liftIO $ setUnicodeLocale $ fromJust $ getLocale conf
     Int.httpServe (map listenToInt $ getListen conf)
                   (fmap backendToInt $ getBackend conf)
                   (fromJust $ getHostname  conf)
@@ -68,9 +69,10 @@ simpleHttpServe config handler = do
 -- | Starts serving HTTP requests using the given handler, with settings from
 -- the 'Config' passed in. This function never returns; to shut down the HTTP
 -- server, kill the controlling thread.
-httpServe :: Config Snap () -> Snap () -> IO ()
+httpServe :: (MonadCatchIO m, Functor m) => Config (SnapT m) () -> SnapT m ()
+          -> m ()
 httpServe config handler = do
-    mapM_ (output . ("Listening on "++) . show) $ getListen conf
+    liftIO $ mapM_ (output . ("Listening on "++) . show) $ getListen conf
     serve handler `finally` output "\nShutting down..."
   where
     conf     = completeConfig config
@@ -85,8 +87,9 @@ httpServe config handler = do
 -- from the options given on the command-line, as returned by
 -- 'commandLineConfig'. This function never returns; to shut down the HTTP
 -- server, kill the controlling thread.
-quickHttpServe :: Snap () -> IO ()
-quickHttpServe m = commandLineConfig emptyConfig >>= \c -> httpServe c m
+quickHttpServe :: (MonadCatchIO m, Functor m) => SnapT m () -> m ()
+quickHttpServe m = liftIO (commandLineConfig emptyConfig) >>= \c ->
+                   httpServe c m
 
 
 ------------------------------------------------------------------------------
diff --git a/src/Snap/Http/Server/Config.hs b/src/Snap/Http/Server/Config.hs
index 38763e1..619b27b 100644
--- a/src/Snap/Http/Server/Config.hs
+++ b/src/Snap/Http/Server/Config.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE UndecidableInstances #-}
 
 {-|
 
@@ -88,7 +89,7 @@ data ConfigBackend = ConfigSimpleBackend
 --
 -- Any fields which are unspecified in the 'Config' passed to 'httpServe' (and
 -- this is the norm) are filled in with default values from 'defaultConfig'.
-data MonadSnap m => Config m a = Config
+data Config m a = Config
     { hostname     :: Maybe ByteString
       -- ^ The name of the server
     , listen       :: [ConfigListen]
@@ -113,7 +114,7 @@ data MonadSnap m => Config m a = Config
 
 
 ------------------------------------------------------------------------------
-instance MonadSnap m => Show (Config m a) where
+instance MonadSnap im m => Show (Config m a) where
     show c = "Config {" ++ concat (intersperse ", " $ filter (/="") $ map ($c)
         [ showM "hostname" . hostname
         , showL "listen" . listen
@@ -133,12 +134,12 @@ instance MonadSnap m => Show (Config m a) where
 ------------------------------------------------------------------------------
 -- | Returns a completely empty 'Config'. Equivalent to 'mempty' from
 -- 'Config''s 'Monoid' instance.
-emptyConfig :: MonadSnap m => Config m a
+emptyConfig :: MonadSnap im m => Config m a
 emptyConfig = mempty
 
 
 ------------------------------------------------------------------------------
-instance MonadSnap m => Monoid (Config m a) where
+instance MonadSnap im m => Monoid (Config m a) where
     mempty = Config
         { hostname     = Nothing
         , listen       = []
@@ -179,7 +180,7 @@ instance MonadSnap m => Monoid (Config m a) where
 -- > verbose      = True
 -- > errorHandler = prints the error message
 --
-defaultConfig :: MonadSnap m => Config m a
+defaultConfig :: (MonadSnap im m, Monad im) => Config m a
 defaultConfig = Config
     { hostname     = Just "localhost"
     , listen       = []
@@ -205,7 +206,7 @@ defaultConfig = Config
 -- | Completes a partial 'Config' by filling in the unspecified values with
 -- the default values from 'defaultConfig'.  Also, if no listeners are
 -- specified, adds a http listener on 0.0.0.0:8000
-completeConfig :: MonadSnap m => Config m a -> Config m a
+completeConfig :: (MonadSnap im m, Monad im) => Config m a -> Config m a
 completeConfig c = case listen c' of
                     [] -> addListen (ListenHttp "0.0.0.0" 8000) c'
                     _  -> c'
@@ -217,7 +218,7 @@ completeConfig c = case listen c' of
 -- The Config data type allows a list of listen ports, but the command line
 -- options only allow one http and one https listener.  This data structure
 -- is used during option parsing
-data MonadSnap m => OptionData m a = OptionData
+data OptionData m a = OptionData
     { config  :: Config m a
     , bind    :: Maybe ByteString
     , port    :: Maybe Int
@@ -229,7 +230,7 @@ data MonadSnap m => OptionData m a = OptionData
 
 
 ------------------------------------------------------------------------------
-instance MonadSnap m => Monoid (OptionData m a) where
+instance MonadSnap im m => Monoid (OptionData m a) where
     mempty = OptionData
         { config  = mempty
         , bind    = Nothing
@@ -252,7 +253,7 @@ instance MonadSnap m => Monoid (OptionData m a) where
 
 ------------------------------------------------------------------------------
 -- | These are the default values for the options
-defaultOptions :: MonadSnap m => OptionData m a
+defaultOptions :: (MonadSnap im m, Monad im) => OptionData m a
 defaultOptions = OptionData
     { config  = defaultConfig
     , bind    = Just "0.0.0.0"
@@ -266,7 +267,7 @@ defaultOptions = OptionData
 
 ------------------------------------------------------------------------------
 -- | Convert options to config
-optionsToConfig :: MonadSnap m => OptionData m a -> Config m a
+optionsToConfig :: MonadSnap im m => OptionData m a -> Config m a
 optionsToConfig o = mconcat $ [config o] ++ http ++ https
     where lhttp  = maybe2 [] ListenHttp  (bind o) (port o)
           lhttps = maybe4 [] ListenHttps (sslbind o)
@@ -283,7 +284,7 @@ optionsToConfig o = mconcat $ [config o] ++ http ++ https
 
 ------------------------------------------------------------------------------
 -- | Convert config to options
-configToOptions :: MonadSnap m => Config m a -> OptionData m a
+configToOptions :: MonadSnap im m => Config m a -> OptionData m a
 configToOptions c = OptionData
     { config  = c
     , bind    = Nothing
@@ -308,7 +309,7 @@ configToOptions c = OptionData
 -- as opposed to a @'OptionData' m@, because if the @--help@ option is given,
 -- the set of command-line options no longer describe a config, but an action
 -- (printing out the usage message).
-options :: MonadSnap m => OptionData m a -> [OptDescr (Maybe (OptionData m a))]
+options :: (MonadSnap im m, Monad im) => OptionData m a -> [OptDescr (Maybe 
(OptionData m a))]
 options defaults =
     [ Option [] ["hostname"]
              (ReqArg (Just . setConfig setHostname . U.fromString) "NAME")
@@ -378,7 +379,7 @@ options defaults =
 -- parameter.
 --
 -- On Unix systems, the locale is read from the @LANG@ environment variable.
-commandLineConfig :: MonadSnap m => Config m a -> IO (Config m a)
+commandLineConfig :: (MonadSnap im m, Monad im) => Config m a -> IO (Config m 
a)
 commandLineConfig defaults = do
     args <- getArgs
     prog <- getProgName
@@ -407,100 +408,100 @@ commandLineConfig defaults = do
 
 
 ------------------------------------------------------------------------------
-getHostname :: MonadSnap m => Config m a -> Maybe ByteString
+getHostname :: MonadSnap im m => Config m a -> Maybe ByteString
 getHostname = hostname
 
 
 ------------------------------------------------------------------------------
-getListen :: MonadSnap m => Config m a -> [ConfigListen]
+getListen :: MonadSnap im m => Config m a -> [ConfigListen]
 getListen = listen
 
 
 ------------------------------------------------------------------------------
-getAccessLog :: MonadSnap m => Config m a -> Maybe (Maybe FilePath)
+getAccessLog :: MonadSnap im m => Config m a -> Maybe (Maybe FilePath)
 getAccessLog = accessLog
 
 
 ------------------------------------------------------------------------------
-getErrorLog :: MonadSnap m => Config m a -> Maybe (Maybe FilePath)
+getErrorLog :: MonadSnap im m => Config m a -> Maybe (Maybe FilePath)
 getErrorLog = errorLog
 
 
 ------------------------------------------------------------------------------
-getLocale :: MonadSnap m => Config m a -> Maybe String
+getLocale :: MonadSnap im m => Config m a -> Maybe String
 getLocale = locale
 
 
 ------------------------------------------------------------------------------
-getBackend :: MonadSnap m => Config m a -> Maybe ConfigBackend
+getBackend :: MonadSnap im m => Config m a -> Maybe ConfigBackend
 getBackend = backend
 
 ------------------------------------------------------------------------------
-getCompression :: MonadSnap m => Config m a -> Maybe Bool
+getCompression :: MonadSnap im m => Config m a -> Maybe Bool
 getCompression = compression
 
 
 ------------------------------------------------------------------------------
-getVerbose :: MonadSnap m => Config m a -> Maybe Bool
+getVerbose :: MonadSnap im m => Config m a -> Maybe Bool
 getVerbose = verbose
 
 
 ------------------------------------------------------------------------------
-getErrorHandler :: MonadSnap m => Config m a -> Maybe (SomeException -> m ())
+getErrorHandler :: MonadSnap im m => Config m a -> Maybe (SomeException -> m 
())
 getErrorHandler = errorHandler
 
 
 ------------------------------------------------------------------------------
-getOther :: MonadSnap m => Config m a -> Maybe a
+getOther :: MonadSnap im m => Config m a -> Maybe a
 getOther = other
 
 
 ------------------------------------------------------------------------------
-setHostname :: MonadSnap m => ByteString -> Config m a -> Config m a
+setHostname :: MonadSnap im m => ByteString -> Config m a -> Config m a
 setHostname a m = m {hostname = Just a}
 
 
 ------------------------------------------------------------------------------
-addListen :: MonadSnap m => ConfigListen -> Config m a -> Config m a
+addListen :: MonadSnap im m => ConfigListen -> Config m a -> Config m a
 addListen a m = m {listen = a : listen m}
 
 
 ------------------------------------------------------------------------------
-setAccessLog :: MonadSnap m => Maybe FilePath -> Config m a -> Config m a
+setAccessLog :: MonadSnap im m => Maybe FilePath -> Config m a -> Config m a
 setAccessLog a m = m {accessLog = Just a}
 
 
 ------------------------------------------------------------------------------
-setErrorLog :: MonadSnap m => Maybe FilePath -> Config m a -> Config m a
+setErrorLog :: MonadSnap im m => Maybe FilePath -> Config m a -> Config m a
 setErrorLog a m = m {errorLog = Just a}
 
 
 ------------------------------------------------------------------------------
-setLocale :: MonadSnap m => String -> Config m a -> Config m a
+setLocale :: MonadSnap im m => String -> Config m a -> Config m a
 setLocale a m = m {locale = Just a}
 
 
 ------------------------------------------------------------------------------
-setBackend :: MonadSnap m => ConfigBackend -> Config m a -> Config m a
+setBackend :: MonadSnap im m => ConfigBackend -> Config m a -> Config m a
 setBackend a m = m { backend = Just a}
 
 
 ------------------------------------------------------------------------------
-setCompression :: MonadSnap m => Bool -> Config m a -> Config m a
+setCompression :: MonadSnap im m => Bool -> Config m a -> Config m a
 setCompression a m = m {compression = Just a}
 
 
 ------------------------------------------------------------------------------
-setVerbose :: MonadSnap m => Bool -> Config m a -> Config m a
+setVerbose :: MonadSnap im m => Bool -> Config m a -> Config m a
 setVerbose a m = m {verbose = Just a}
 
 
 ------------------------------------------------------------------------------
-setErrorHandler :: MonadSnap m => (SomeException -> m ()) -> Config m a
+setErrorHandler :: MonadSnap im m => (SomeException -> m ()) -> Config m a
                 -> Config m a
 setErrorHandler a m = m {errorHandler = Just a}
 
 
 ------------------------------------------------------------------------------
-setOther :: MonadSnap m => a -> Config m a -> Config m a
+setOther :: MonadSnap im m => a -> Config m a -> Config m a
 setOther a m = m {other = Just a}
diff --git a/src/Snap/Internal/Http/Server.hs b/src/Snap/Internal/Http/Server.hs
index 81db8fd..1bed699 100644
--- a/src/Snap/Internal/Http/Server.hs
+++ b/src/Snap/Internal/Http/Server.hs
@@ -3,13 +3,15 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE FlexibleContexts #-}
 
 module Snap.Internal.Http.Server where
 
 ------------------------------------------------------------------------------
 import           Control.Arrow (first, second)
 import           Control.Monad.State.Strict
-import           Control.Exception
+import           Control.Exception (SomeException, AsyncException)
+import           Control.Monad.CatchIO
 import           Data.Char
 import           Data.CIByteString
 import           Data.Binary.Put
@@ -62,11 +64,11 @@ import qualified Paths_snap_server as V
 --
 -- Note that we won't be bothering end users with this -- the details will be
 -- hidden inside the Snap monad
-type ServerHandler = (ByteString -> IO ())
-                   -> Request
-                   -> Iteratee ByteString IO (Request,Response)
+type ServerHandler m = (ByteString -> m ())
+                     -> Request
+                     -> Iteratee ByteString m (Request,Response)
 
-type ServerMonad = StateT ServerState (Iteratee ByteString IO)
+type ServerMonad m = StateT ServerState (Iteratee ByteString m)
 
 data ListenPort = HttpPort  ByteString Int                   -- (bind address, 
port)
                 | HttpsPort ByteString Int FilePath FilePath -- (bind address, 
port, path to certificate, path to key)
@@ -91,12 +93,13 @@ data ServerState = ServerState
     }
 
 ------------------------------------------------------------------------------
-runServerMonad :: ByteString                     -- ^ local host name
+runServerMonad :: MonadIO m
+               => ByteString                     -- ^ local host name
                -> SessionInfo                    -- ^ session port information
                -> (Request -> Response -> IO ()) -- ^ access log function
                -> (ByteString -> IO ())          -- ^ error log function
-               -> ServerMonad a                  -- ^ monadic action to run
-               -> Iteratee ByteString IO a
+               -> ServerMonad m a               -- ^ monadic action to run
+               -> Iteratee ByteString m a
 runServerMonad lh s la le m = evalStateT m st
   where
     st = ServerState False lh s la le
@@ -107,67 +110,72 @@ runServerMonad lh s la le m = evalStateT m st
 
 
 ------------------------------------------------------------------------------
-httpServe :: [ListenPort]        -- ^ ports to listen on
+httpServe :: MonadCatchIO m
+          => [ListenPort]        -- ^ ports to listen on
           -> Maybe EventLoopType -- ^ Specify a given event loop, otherwise a 
default is picked
           -> ByteString          -- ^ local hostname (server name)
           -> Maybe FilePath      -- ^ path to the access log
           -> Maybe FilePath      -- ^ path to the error log
-          -> ServerHandler       -- ^ handler procedure
-          -> IO ()
+          -> ServerHandler m     -- ^ handler procedure
+          -> m ()
 httpServe ports mevType localHostname alogPath elogPath handler =
     withLoggers alogPath elogPath
                 (\(alog, elog) -> spawnAll alog elog)
 
   where
     --------------------------------------------------------------------------
+    spawnAll :: MonadCatchIO m => Maybe Logger -> Maybe Logger -> m ()
     spawnAll alog elog = {-# SCC "httpServe/spawnAll" #-} do
 
         let evType = maybe defaultEvType id mevType
 
-        logE elog $ S.concat [ "Server.httpServe: START ("
-                             , toBS $ Prelude.show evType, ")"]
+        liftIO $ logE elog $ S.concat [ "Server.httpServe: START ("
+                                      , toBS $ Prelude.show evType, ")"]
 
         let initHttps = foldr (\p b -> b || case p of { (HttpsPort _ _ _ _) -> 
True; _ -> False;}) False ports
 
         if initHttps
-            then TLS.initTLS
+            then liftIO TLS.initTLS
             else return ()
             
-        nports <- mapM bindPort ports
+        nports <- mapM (liftIO . bindPort) ports
             
-        (runEventLoop evType nports numCapabilities (logE elog) $
+        (liftIO $ runEventLoop evType nports numCapabilities (logE elog) $
                       runHTTP alog elog handler localHostname) `finally` do
 
-            logE elog "Server.httpServe: SHUTDOWN"
+            liftIO $ logE elog "Server.httpServe: SHUTDOWN"
 
             if initHttps
-                then TLS.stopTLS
+                then liftIO TLS.stopTLS
                 else return ()
 
-            logE elog "Server.httpServe: BACKEND STOPPED"
-
-    --------------------------------------------------------------------------
-    bindPort (HttpPort  baddr port)          = bindHttp  baddr port
-    bindPort (HttpsPort baddr port cert key) = TLS.bindHttps baddr port cert 
key
-
+            liftIO $ logE elog "Server.httpServe: BACKEND STOPPED"
 
     --------------------------------------------------------------------------
     runEventLoop EventLoopSimple       = simpleEventLoop
     runEventLoop EventLoopLibEv        = libEvEventLoop
 
 
-    --------------------------------------------------------------------------
-    maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . newLogger
+--------------------------------------------------------------------------
+bindPort (HttpPort  baddr port)          = bindHttp  baddr port
+bindPort (HttpsPort baddr port cert key) = TLS.bindHttps baddr port cert key
 
 
-    --------------------------------------------------------------------------
-    withLoggers afp efp =
-        bracket (do alog <- maybeSpawnLogger afp
-                    elog <- maybeSpawnLogger efp
-                    return (alog, elog))
-                (\(alog, elog) -> do
-                    maybe (return ()) stopLogger alog
-                    maybe (return ()) stopLogger elog)
+--------------------------------------------------------------------------
+maybeSpawnLogger :: MonadIO m => Maybe FilePath -> m (Maybe Logger)
+maybeSpawnLogger = maybe (return Nothing) $ (liftM Just) . liftIO . newLogger
+
+
+--------------------------------------------------------------------------
+withLoggers :: MonadCatchIO m => Maybe FilePath -> Maybe FilePath
+            -> ((Maybe Logger, Maybe Logger) -> m b) -> m b
+withLoggers afp efp =
+    bracket (do alog <- maybeSpawnLogger afp
+                elog <- maybeSpawnLogger efp
+                return (alog, elog))
+            (\(alog, elog) -> do
+                maybe (return ()) (liftIO . stopLogger) alog
+                maybe (return ()) (liftIO . stopLogger) elog)
 
 
 ------------------------------------------------------------------------------
@@ -215,9 +223,10 @@ logA' logger req rsp = do
 
 
 ------------------------------------------------------------------------------
-runHTTP :: Maybe Logger                  -- ^ access logger
+runHTTP :: MonadCatchIO m
+        => Maybe Logger                  -- ^ access logger
         -> Maybe Logger                  -- ^ error logger
-        -> ServerHandler                 -- ^ handler procedure
+        -> ServerHandler m               -- ^ handler procedure
         -> ByteString                    -- ^ local host name
         -> SessionInfo                   -- ^ session port information
         -> Enumerator ByteString IO ()   -- ^ read end of socket
@@ -225,19 +234,19 @@ runHTTP :: Maybe Logger                  -- ^ access 
logger
         -> (FilePath -> Int64 -> Int64 -> IO ())
                                          -- ^ sendfile end
         -> IO ()                         -- ^ timeout tickler
-        -> IO ()
+        -> m ()
 runHTTP alog elog handler lh sinfo readEnd writeEnd onSendFile tickle =
     go `catches` [ Handler $ \(e :: AsyncException) -> do
-                       throwIO e
+                       liftIO $ throw e
 
                  , Handler $ \(e :: SomeException) ->
-                       logE elog $ S.concat [ logPrefix , bshow e ] ]
+                       liftIO $ logE elog $ S.concat [ logPrefix , bshow e ] ]
 
   where
     logPrefix = S.concat [ "[", remoteAddress sinfo, "]: error: " ]
 
     go = do
-        buf <- mkIterateeBuffer
+        buf <- liftIO mkIterateeBuffer
         let iter1 = runServerMonad lh sinfo (logA alog) (logE elog) $
                                    httpSession writeEnd buf onSendFile tickle
                                    handler
@@ -245,7 +254,7 @@ runHTTP alog elog handler lh sinfo readEnd writeEnd 
onSendFile tickle =
 
         debug "runHTTP/go: prepping iteratee for start"
 
-        step <- liftIO $ runIteratee iter
+        step <- runIteratee iter
 
         debug "runHTTP/go: running..."
         run_ $ readEnd step
@@ -263,24 +272,25 @@ snapServerVersion = SC.pack $ showVersion $ V.version
 
 
 ------------------------------------------------------------------------------
-logAccess :: Request -> Response -> ServerMonad ()
+logAccess :: MonadIO m => Request -> Response -> ServerMonad m ()
 logAccess req rsp = gets _logAccess >>= (\l -> liftIO $ l req rsp)
 
 
 ------------------------------------------------------------------------------
-logError :: ByteString -> ServerMonad ()
+logError :: MonadIO m => ByteString -> ServerMonad m ()
 logError s = gets _logError >>= (\l -> liftIO $ l s)
 
 
 ------------------------------------------------------------------------------
 -- | Runs an HTTP session.
-httpSession :: Iteratee ByteString IO ()     -- ^ write end of socket
+httpSession :: MonadIO m
+            => Iteratee ByteString IO ()     -- ^ write end of socket
             -> ForeignPtr CChar              -- ^ iteratee buffer
             -> (FilePath -> Int64 -> Int64 -> IO ())
                                              -- ^ sendfile continuation
             -> IO ()                         -- ^ timeout tickler
-            -> ServerHandler                 -- ^ handler procedure
-            -> ServerMonad ()
+            -> ServerHandler m               -- ^ handler procedure
+            -> ServerMonad m ()
 httpSession writeEnd' ibuf onSendFile tickle handler = do
 
     let writeEnd1 = I.unsafeBufferIterateeWithBuffer ibuf writeEnd'
@@ -308,7 +318,7 @@ httpSession writeEnd' ibuf onSendFile tickle handler = do
 
           logerr <- gets _logError
 
-          (req',rspOrig) <- lift $ handler logerr req
+          (req',rspOrig) <- lift $ handler (liftIO . logerr) req
 
           liftIO $ debug $ "Server.httpSession: finished running user handler"
 
@@ -330,7 +340,7 @@ httpSession writeEnd' ibuf onSendFile tickle handler = do
 
                skipStep <- liftIO $ runIteratee $
                            iterateeDebugWrapper "httpSession/skipToEof" 
skipToEof
-               lift $ rqEnum skipStep
+               lift $ liftIterIO $ rqEnum skipStep
 
           liftIO $ debug $ "Server.httpSession: request body skipped, " ++
                            "sending response"
@@ -360,9 +370,9 @@ httpSession writeEnd' ibuf onSendFile tickle handler = do
 
 
 ------------------------------------------------------------------------------
-checkExpect100Continue :: Request
+checkExpect100Continue :: MonadIO m => Request
                        -> Step ByteString IO ()
-                       -> ServerMonad ()
+                       -> ServerMonad m ()
 checkExpect100Continue req writeEnd = do
     let mbEx = getHeaders "Expect" req
 
@@ -384,7 +394,7 @@ checkExpect100Continue req writeEnd = do
 
 
 ------------------------------------------------------------------------------
-receiveRequest :: ServerMonad (Maybe Request)
+receiveRequest :: MonadIO m => ServerMonad m (Maybe Request)
 receiveRequest = do
     debug "receiveRequest: entered"
     mreq <- {-# SCC "receiveRequest/parseRequest" #-} lift $
@@ -412,7 +422,7 @@ receiveRequest = do
     --
     -- if no content-length and no chunked encoding, enumerate the entire
     -- socket and close afterwards
-    setEnumerator :: Request -> ServerMonad ()
+    setEnumerator :: MonadIO m => Request -> ServerMonad m ()
     setEnumerator req = {-# SCC "receiveRequest/setEnumerator" #-} do
         if isChunked
           then do
@@ -428,7 +438,7 @@ receiveRequest = do
                           ((== ["chunked"]) . map toCI)
                           (Map.lookup "transfer-encoding" hdrs)
 
-        hasContentLength :: Int64 -> ServerMonad ()
+        hasContentLength :: MonadIO m => Int64 -> ServerMonad m ()
         hasContentLength len = do
             liftIO $ debug $ "receiveRequest/setEnumerator: " ++
                              "request had content-length " ++ Prelude.show len
@@ -444,7 +454,7 @@ receiveRequest = do
 
                 joinI $ takeExactly len st'
 
-        noContentLength :: Request -> ServerMonad ()
+        noContentLength :: MonadIO m => Request -> ServerMonad m ()
         noContentLength req = liftIO $ do
             debug ("receiveRequest/setEnumerator: " ++
                    "request did NOT have content-length")
@@ -462,7 +472,7 @@ receiveRequest = do
 
 
     --------------------------------------------------------------------------
-    parseForm :: Request -> ServerMonad Request
+    parseForm :: MonadIO m => Request -> ServerMonad m Request
     parseForm req = {-# SCC "receiveRequest/parseForm" #-}
         if doIt then getIt else return req
       where
@@ -475,7 +485,7 @@ receiveRequest = do
         maximumPOSTBodySize :: Int64
         maximumPOSTBodySize = 10*1024*1024
 
-        getIt :: ServerMonad Request
+        getIt :: MonadIO m => ServerMonad m Request
         getIt = {-# SCC "receiveRequest/parseForm/getIt" #-} do
             liftIO $ debug "parseForm: got application/x-www-form-urlencoded"
             liftIO $ debug "parseForm: reading POST body"
@@ -485,7 +495,7 @@ receiveRequest = do
             step <- liftIO $
                     runIteratee $
                     joinI $ takeNoMoreThan maximumPOSTBodySize consumeStep
-            body <- liftM S.concat $ lift $ enum step
+            body <- liftM S.concat $ lift $ liftIterIO $ enum step
             let newParams = parseUrlEncoded body
 
             liftIO $ debug "parseForm: stuffing 'enumBS body' into request"
@@ -571,24 +581,33 @@ receiveRequest = do
                                   S.break (== (c2w '?')) uri
 
 
+liftIterIO :: (MonadIO m) => Iteratee a IO b -> Iteratee a m b
+liftIterIO iter = Iteratee $ do
+  step <- liftIO $ runIteratee iter
+  return $ case step of
+    Yield x cs -> Yield x cs
+    Error err -> Error err
+    Continue k -> Continue (liftIterIO . k)
+
 ------------------------------------------------------------------------------
 -- Response must be well-formed here
-sendResponse :: forall a . Request
+sendResponse :: forall m a . (MonadIO m
+             => Request
              -> Response
              -> Step ByteString IO a                 -- ^ iteratee write end
              -> (FilePath -> Int64 -> Int64 -> IO a) -- ^ function to call on
                                                      -- sendfile
-             -> ServerMonad (Int64, a)
+             -> ServerMonad m (Int64, a))
 sendResponse req rsp' writeEnd onSendFile = do
     rsp <- fixupResponse rsp'
     let !headerString = mkHeaderString rsp
 
     (!x,!bs) <- case (rspBody rsp) of
-                  (Enum e)             -> lift $ whenEnum headerString rsp e
-                  (SendFile f Nothing) -> lift $
+                  (Enum e)             -> lift $ liftIterIO $ whenEnum 
headerString rsp e
+                  (SendFile f Nothing) -> lift $ liftIterIO $
                                           whenSendFile headerString rsp f 0
                   (SendFile f (Just (st,_))) ->
-                      lift $ whenSendFile headerString rsp f st
+                      lift $ liftIterIO $ whenSendFile headerString rsp f st
 
     debug "sendResponse: response sent"
 
@@ -660,7 +679,7 @@ sendResponse req rsp' writeEnd onSendFile = do
 
 
     --------------------------------------------------------------------------
-    noCL :: Response -> ServerMonad Response
+    noCL :: Response -> ServerMonad m Response
     noCL r =
         {-# SCC "noCL" #-}
         do
@@ -686,7 +705,7 @@ sendResponse req rsp' writeEnd onSendFile = do
 
 
     --------------------------------------------------------------------------
-    hasCL :: Int64 -> Response -> ServerMonad Response
+    hasCL :: Int64 -> Response -> ServerMonad m Response
     hasCL cl r =
         {-# SCC "hasCL" #-}
         do
@@ -707,7 +726,7 @@ sendResponse req rsp' writeEnd onSendFile = do
 
 
     --------------------------------------------------------------------------
-    setFileSize :: FilePath -> Response -> ServerMonad Response
+    setFileSize :: MonadIO m => FilePath -> Response -> ServerMonad m Response
     setFileSize fp r =
         {-# SCC "setFileSize" #-}
         do
@@ -723,7 +742,7 @@ sendResponse req rsp' writeEnd onSendFile = do
 
 
     --------------------------------------------------------------------------
-    fixupResponse :: Response -> ServerMonad Response
+    fixupResponse :: Response -> ServerMonad m Response
     fixupResponse r = {-# SCC "fixupResponse" #-} do
         let r' = deleteHeader "Content-Length" r
 
@@ -771,7 +790,7 @@ sendResponse req rsp' writeEnd onSendFile = do
                    
 
 ------------------------------------------------------------------------------
-checkConnectionClose :: (Int, Int) -> Headers -> ServerMonad ()
+checkConnectionClose :: Monad m => (Int, Int) -> Headers -> ServerMonad m ()
 checkConnectionClose ver hdrs =
     -- For HTTP/1.1:
     --   if there is an explicit Connection: close, close the socket.
diff --git a/src/Snap/Internal/Http/Server/Backend.hs 
b/src/Snap/Internal/Http/Server/Backend.hs
index f9bd4d6..6b6a9d3 100644
--- a/src/Snap/Internal/Http/Server/Backend.hs
+++ b/src/Snap/Internal/Http/Server/Backend.hs
@@ -23,18 +23,18 @@ data SessionInfo = SessionInfo
     , isSecure      :: Bool
     }
 
-type SessionHandler =  SessionInfo                           -- ^ session port 
information
-                    -> Enumerator ByteString IO ()           -- ^ read end of 
socket
-                    -> Iteratee ByteString IO ()             -- ^ write end of 
socket
-                    -> (FilePath -> Int64 -> Int64 -> IO ()) -- ^ sendfile end
-                    -> IO ()                                 -- ^ timeout 
tickler
-                    -> IO ()
+type SessionHandler m =  SessionInfo                           -- ^ session 
port information
+                      -> Enumerator ByteString IO ()           -- ^ read end 
of socket
+                      -> Iteratee ByteString IO ()             -- ^ write end 
of socket
+                      -> (FilePath -> Int64 -> Int64 -> IO ()) -- ^ sendfile 
end
+                      -> IO ()                                 -- ^ timeout 
tickler
+                      -> m ()
 
-type EventLoop = [ListenSocket]                -- ^ list of ports
-               -> Int                          -- ^ number of capabilities
-               -> (ByteString -> IO ())        -- ^ error log
-               -> SessionHandler               -- ^ session handler
-               -> IO ()
+type EventLoop m = [ListenSocket]                -- ^ list of ports
+                 -> Int                          -- ^ number of capabilities
+                 -> (ByteString -> IO ())        -- ^ error log
+                 -> SessionHandler m             -- ^ session handler
+                 -> m ()
 
 
 {- For performance reasons, we do not implement this as a class
diff --git a/src/Snap/Internal/Http/Server/LibevBackend.hs 
b/src/Snap/Internal/Http/Server/LibevBackend.hs
index 006f7bc..ce95f73 100644
--- a/src/Snap/Internal/Http/Server/LibevBackend.hs
+++ b/src/Snap/Internal/Http/Server/LibevBackend.hs
@@ -14,6 +14,7 @@ module Snap.Internal.Http.Server.LibevBackend
 #ifndef LIBEV
 
 import Control.Exception
+import Control.Monad.Trans
 import Data.Typeable
 import Snap.Internal.Http.Server.Backend
 
@@ -21,8 +22,8 @@ data LibevException = LibevException String
   deriving (Show, Typeable)
 instance Exception LibevException
 
-libEvEventLoop :: EventLoop
-libEvEventLoop _ _ _ _ = throwIO $ LibevException "libev event loop is not 
supported"
+libEvEventLoop :: MonadIO m => EventLoop m
+libEvEventLoop _ _ _ _ = liftIO $ throwIO $ LibevException "libev event loop 
is not supported"
 
 #else
 
diff --git a/src/Snap/Internal/Http/Server/SimpleBackend.hs 
b/src/Snap/Internal/Http/Server/SimpleBackend.hs
index 4554871..c85016b 100644
--- a/src/Snap/Internal/Http/Server/SimpleBackend.hs
+++ b/src/Snap/Internal/Http/Server/SimpleBackend.hs
@@ -15,8 +15,9 @@ module Snap.Internal.Http.Server.SimpleBackend
 import           Control.Monad.Trans
 
 import           Control.Concurrent hiding (yield)
-import           Control.Exception
+import           Control.Exception (SomeException, AsyncException)
 import           Control.Monad
+import           Control.Monad.CatchIO
 import           Data.ByteString (ByteString)
 import qualified Data.ByteString as S
 import           Data.ByteString.Internal (c2w)
@@ -59,7 +60,7 @@ data EventLoopCpu = EventLoopCpu
     , _exitMVar        :: !(MVar ())
     }
 
-simpleEventLoop :: EventLoop
+simpleEventLoop :: EventLoop m
 simpleEventLoop sockets cap elog handler = do
     loops <- Prelude.mapM (newLoop sockets handler elog) [0..(cap-1)]
 
@@ -72,10 +73,10 @@ simpleEventLoop sockets cap elog handler = do
         mapM Listen.closeSocket sockets
 
 newLoop :: [ListenSocket]
-        -> SessionHandler
+        -> SessionHandler m
         -> (S.ByteString -> IO ())
         -> Int
-        -> IO EventLoopCpu
+        -> m EventLoopCpu
 newLoop sockets handler elog cpu = do
     tt         <- TT.new
     exit       <- newEmptyMVar
@@ -89,15 +90,16 @@ stopLoop loop = block $ do
     Prelude.mapM_ killThread $ _acceptThreads loop
     killThread $ _timeoutThread loop
 
-acceptThread :: SessionHandler 
+acceptThread :: MonadCatchIO m
+             => SessionHandler m
              -> TimeoutTable 
              -> (S.ByteString -> IO ()) 
              -> Int 
              -> ListenSocket 
-             -> IO ()
+             -> m ()
 acceptThread handler tt elog cpu sock = loop
   where
-    loop = do
+    loop = liftIO $ do
         debug $ "acceptThread: calling accept()"
         (s,addr) <- accept $ Listen.listenSocket sock
         debug $ "acceptThread: accepted connection from remote: " ++ show addr
@@ -107,7 +109,9 @@ acceptThread handler tt elog cpu sock = loop
     go = runSession handler tt sock
  
     cleanup = [
-                Handler $ \(e :: SomeException) -> elog $ S.concat [ 
"SimpleBackend.acceptThread: ", S.pack . map c2w $ show e]
+                Handler $ \(e :: SomeException) -> liftIO $
+                  elog $ S.concat [ "SimpleBackend.acceptThread: "
+                                  , S.pack . map c2w $ show e]
               ]
 
 timeoutThread :: TimeoutTable -> MVar () -> IO ()
@@ -145,38 +149,44 @@ instance Show AddressNotSupportedException where
 instance Exception AddressNotSupportedException
 
 
-runSession :: SessionHandler -> TimeoutTable -> ListenSocket -> Socket -> 
SockAddr -> IO ()
+runSession :: MonadCatchIO m
+           => SessionHandler m
+           -> TimeoutTable
+           -> ListenSocket
+           -> Socket
+           -> SockAddr
+           -> m ()
 runSession handler tt lsock sock addr = do
     let fd = fdSocket sock
-    curId <- myThreadId
+    curId <- liftIO myThreadId
 
     debug $ "Backend.withConnection: running session: " ++ show addr
-    labelThread curId $ "connHndl " ++ show fd
+    liftIO $ labelThread curId $ "connHndl " ++ show fd
 
-    (rport,rhost) <-
+    (rport,rhost) <- liftIO $
         case addr of
           SockAddrInet p h -> do
              h' <- inet_ntoa h
              return (fromIntegral p, S.pack $ map c2w h')
-          x -> throwIO $ AddressNotSupportedException $ show x
+          x -> throw $ AddressNotSupportedException $ show x
 
-    laddr <- getSocketName sock
+    laddr <- liftIO $ getSocketName sock
 
-    (lport,lhost) <-
+    (lport,lhost) <- liftIO $
         case laddr of
           SockAddrInet p h -> do
              h' <- inet_ntoa h
              return (fromIntegral p, S.pack $ map c2w h')
-          x -> throwIO $ AddressNotSupportedException $ show x
+          x -> throw $ AddressNotSupportedException $ show x
 
     let sinfo = SessionInfo lhost lport rhost rport $ Listen.isSecure lsock
     let curHash = hashString $ show curId
     let timeout = tickleTimeout tt curId curHash
 
-    timeout
+    liftIO timeout
 
-    bracket (Listen.createSession lsock 8192 fd (threadWaitRead $ fromIntegral 
fd))
-            (\session -> block $ do
+    bracket (liftIO $ Listen.createSession lsock 8192 fd (threadWaitRead $ 
fromIntegral fd))
+            (\session -> block $ liftIO $ do
                  debug "thread killed, closing socket"
 
                  -- remove thread from timeout table
-----------------------------------------------------------------------


hooks/post-receive
-- 
snap-server
_______________________________________________
Snap mailing list
[email protected]
http://mailman-mail5.webfaction.com/listinfo/snap

Reply via email to