MFlow-0.4.5.10: src/MFlow/Forms/WebApi.hs
-----------------------------------------------------------------------------
--
-- A Haskell formlet is the combination of a parameter parser to read input plus a writer to generate HTTP
-- output
--
-- I use this similarity to create parsec-like combinators that use the formlet monad in MFlow
--(the View monad) to parse the web service parameters and to generate the output.
--
-- This service below implements a service that sum or multiply two Integers.
--
-- > parserService :: View Html IO ()
-- > parserService=
-- > do rest "sum" ; disp $ (+) <$> wint "t1" <*> wint "t2"
-- > <|> do rest "prod" ; disp $ (*) <$> wint "t1" <*> wint "t2"
-- > <?> do -- blaze Html
-- > h1 << "ERROR. API usage:"
-- > h3 << "http://server/api/sum?t1=[Int]&t2=[Int]"
-- > h3 << "http://server/api/prod?t1=[Int]&t2=[Int]"
-- > where
-- > asks w= ask $ w >> stop
-- > wint p= wparam p :: View Html IO Int
--
-- Can be called with:
--
-- > mainParser = runNavigation "apiparser" . step . asks (parserService >> stop)
--
-- or
--
-- > mainParser =do
-- > addMessageFlows[("apiparser",wstateless parserService)]
-- > wait $ run 80 waiMessageFlow
-----------------------------------------------------------------------------
module MFlow.Forms.WebApi (
restp, rest, wparam, disp,(<?>)
) where
import MFlow.Forms.Internals
import MFlow.Forms(stop,(++>))
import Control.Monad.State
import Data.Typeable
import Data.Monoid
-- | Get the next segment of the REST path. if there is no one or if the data does not match
-- with the type expected, then it return invalid.
-- Therefore a monadic sequence in the View monad will not continue
restp :: (Monad m,Functor m, FormInput v,Typeable a,Read a) => View v m a
restp = View $ do
mr <- getRestParam
return $ FormElm mempty mr
-- | Check that the next rest segment has a certain value. It return invalid otherwise.
-- therefore a monadic sequence in the View monad will not continue
rest v= do
r <- restp
if r==v then return v
else
modify (\s -> s{mfPagePath= reverse . tail . reverse $ mfPagePath s}) >> stop
-- | Get a parameter from a GET or POST key-value input.
wparam par= View $ do
mr <- getKeyValueParam par
return $ FormElm mempty mr
-- | append to the output the result of an expression
dispv :: (Monad m, FormInput v) => View v m v -> View v m ()
dispv w= View $ do
FormElm f mx <- runView w
case mx of
Nothing -> return $ FormElm f Nothing
justx@(Just x) -> return $ FormElm (f <> x) $ return ()
-- | append to the output the result of an expression
disp :: (Monad m, FormInput v, Show a) => View v m a -> View v m ()
disp w= View $ do
FormElm f mx <- runView w
case mx of
Nothing -> return $ FormElm f Nothing
justx@(Just x) -> return $ FormElm (f <>fromStr (show x)) $ return ()
-- | error message when a applicative expression do not match
infixl 3 <?>
(<?>) w v= View $ do
r@(FormElm f mx) <- runView w
case mx of
Nothing -> runView $ v ++> stop
Just _ -> return r