happstack simpleHTTP & state monad

Hi all, I'm trying to make a web server that manages its own state. The user can issue commands that modifies the state. I did like below but unfortunatly the state is not keep after a command is issued... What is the right way to do it? Is there any example sites with an internal state with happstack? *data Game = (the state of my game) type NomicServer = ServerPartT (StateT Game IO) launchWebServer :: Game -> IO () launchWebServer initialState = do putStrLn "Starting web server...\nTo connect, drive your browser to \" http://localhost:8000/Login\"" d <- getDataDir simpleHTTP' unpackStateT nullConf $ server d server :: FilePath -> ServerPartT (StateT Game IO) Response server d sh = mconcat [fileServe [] d, do decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096) html <- implSite "http://localhost:8000/" "" nomicSite return $ toResponse html] unpackStateT:: Game -> UnWebT (StateT Game IO) Response -> UnWebT IO Response unpackStateT g w = evalStateT w g --handler for web routes nomicSite :: Site PlayerCommand (NomicServer Html) nomicSite = setDefault (Noop 0) Site { handleSite = \f url -> unRouteT (routedNomicCommands url) f , formatPathSegments = \u -> (toPathSegments u, []) , parsePathSegments = parseSegments fromPathSegments }* Thanks a lot, Corentin

The way you wrote it, you run the state transformer once for each
request. So the state will be available within a single request, but
not between requests. If you want to persist state between requests,
you can use one the the mutable variables available (TVar or MVar are
good choices; IORefs also work, but you have to take care about
concurrency, using e.g. atomicModifyIORef). Create them before calling
simpleHTTP, then pass them in to use them in your handler. You can put
them in a ReaderT to avoid passing them, if you want.
Another choice is to use something like a database or the file system
for persistent state. Databases usually handle most concurrency
problems for you, while file systems don't.
Regards,
Erik
On Thu, Aug 30, 2012 at 7:29 PM, Corentin Dupont
Hi all, I'm trying to make a web server that manages its own state. The user can issue commands that modifies the state. I did like below but unfortunatly the state is not keep after a command is issued... What is the right way to do it? Is there any example sites with an internal state with happstack?
data Game = (the state of my game) type NomicServer = ServerPartT (StateT Game IO)
launchWebServer :: Game -> IO () launchWebServer initialState = do putStrLn "Starting web server...\nTo connect, drive your browser to \"http://localhost:8000/Login\"" d <- getDataDir simpleHTTP' unpackStateT nullConf $ server d
server :: FilePath -> ServerPartT (StateT Game IO) Response server d sh = mconcat [fileServe [] d, do decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096) html <- implSite "http://localhost:8000/" "" nomicSite return $ toResponse html]
unpackStateT:: Game -> UnWebT (StateT Game IO) Response -> UnWebT IO Response unpackStateT g w = evalStateT w g
--handler for web routes nomicSite :: Site PlayerCommand (NomicServer Html) nomicSite = setDefault (Noop 0) Site { handleSite = \f url -> unRouteT (routedNomicCommands url) f , formatPathSegments = \u -> (toPathSegments u, []) , parsePathSegments = parseSegments fromPathSegments }
Thanks a lot, Corentin _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Erik,
yes you're right, I'm experimenting with an IORef now (a TVar would be a
better idea).
I also tried the idea expressed here, to keep the state:
https://groups.google.com/forum/?fromgroups=#!msg/happs/_JSpaJKub0k/oa0K01IB...
But without success so far. The server is returning me the state in the
Response type but I cannot manage to reinject it for the next call :)
Best,
Corentin
On Thu, Aug 30, 2012 at 9:47 PM, Erik Hesselink
The way you wrote it, you run the state transformer once for each request. So the state will be available within a single request, but not between requests. If you want to persist state between requests, you can use one the the mutable variables available (TVar or MVar are good choices; IORefs also work, but you have to take care about concurrency, using e.g. atomicModifyIORef). Create them before calling simpleHTTP, then pass them in to use them in your handler. You can put them in a ReaderT to avoid passing them, if you want.
Another choice is to use something like a database or the file system for persistent state. Databases usually handle most concurrency problems for you, while file systems don't.
Regards,
Erik
On Thu, Aug 30, 2012 at 7:29 PM, Corentin Dupont
wrote: Hi all, I'm trying to make a web server that manages its own state. The user can issue commands that modifies the state. I did like below but unfortunatly the state is not keep after a command is issued... What is the right way to do it? Is there any example sites with an internal state with happstack?
data Game = (the state of my game) type NomicServer = ServerPartT (StateT Game IO)
launchWebServer :: Game -> IO () launchWebServer initialState = do putStrLn "Starting web server...\nTo connect, drive your browser to \"http://localhost:8000/Login\"" d <- getDataDir simpleHTTP' unpackStateT nullConf $ server d
server :: FilePath -> ServerPartT (StateT Game IO) Response server d sh = mconcat [fileServe [] d, do decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096) html <- implSite " http://localhost:8000/" "" nomicSite return $ toResponse html]
unpackStateT:: Game -> UnWebT (StateT Game IO) Response -> UnWebT IO Response unpackStateT g w = evalStateT w g
--handler for web routes nomicSite :: Site PlayerCommand (NomicServer Html) nomicSite = setDefault (Noop 0) Site { handleSite = \f url -> unRouteT (routedNomicCommands url) f , formatPathSegments = \u -> (toPathSegments u, []) , parsePathSegments = parseSegments fromPathSegments }
Thanks a lot, Corentin _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (2)
-
Corentin Dupont
-
Erik Hesselink