I'm trying to make a silly webserver that stores data as State
. I'm using Web.Scotty
. I've used ReaderT before with scotty to access config, but following the same approach doesn't work here. It resets the state on every request.
I want to set the initial state when the program starts, then have that same state stick around for the whole life of the program.
How can I make this work? (The following creates a new state every request)
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty.Trans
import Control.Monad.State (StateT, evalStateT, lift)
import qualified Control.Monad.State as S
import Data.Text.Lazy (Text)
main :: IO ()
main = do
let runner = flip evalStateT "message"
scottyT 3000 runner runner routes
routes :: ScottyT Text (StateT Text IO) ()
routes = do
get "/data" $ do
val <- lift S.get
text val
put "/data/:val" $ do
val <- param "val"
lift $ S.put val
text val
The behaviour you are seeing is definitely the expected one: note the remark on the third argument in the documentation for
scottyT
:What you could do is store the state external to the
StateT
monad so that you can reinstate it in the handler of every action. The most naïve way I can think of to do that would be something like this:but this doesn't really address what should happen if two requests are coming in concurrently, it's just "last one to finish wins".