> -- | Definitions and functions for building a router > module Frame.Router ( > FrameRouter, > fileFolder, > Router, > startRouter > ) where > import Data.List > import Data.Map > import qualified Data.ByteString.Lazy as L > import Control.Monad.State (StateT, runStateT) > import Control.Monad.Reader (ReaderT, runReaderT) > import Frame.GUI > import Frame.Data > import Frame.Config > import Frame.State > import Frame.Types > import Frame.Utilities > import Frame.Validation > import Frame.Model > import Frame.View > class (FrameConfig m, FrameState m, FrameIO m) => FrameRouter m > instance (FrameConfig m, FrameState m, FrameIO m) => FrameRouter m > -- | The 'fileFolder' function maps a URL to a filesystem folder > fileFolder :: FrameRouter m => String -- ^ Folder on the file system > -> [String] -- ^ Exploded URL > -> m Data -- ^ Either an Error404 or the File > fileFolder r fs = do > f <- liftIO $ L.readFile (r ++ implodeUrl fs) `catch` (\_ -> return L.empty) > case L.null f of > True -> return Error404 > False -> return $ File f > -- | A router maps from a path (list of URL parts) to some 'Data' > type Router = ([String] -> StateT Vars (ReaderT Config IO) Data) > {-| > Executes a given router and validators against request information from the > server > -} > startRouter :: Router -- ^ The router being executed > -> Config -- ^ The configuration > -> Validators -- ^ Validators to check fields against > -> [(FieldName, String)] -- ^ Initial fields (from the server) > -> String -- ^ The URL (from the server) > -> String -- ^ The session ID > -> Bool -- ^ Whether this is an Ajax request > -> IO Data -- ^ The data to be returned > startRouter r c@Config{database=db} v vs u id a = let fs = fromList' db vs in > do > (d, _) <- runReaderT (runStateT (r $ explodeURL u) startState{fields=fs, validators=v, post=size fs /= 0, ajax=a}) c{sessionId=id} > return d