{-# LANGUAGE CPP #-} #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 702) {-# LANGUAGE Safe #-} #endif {-# LANGUAGE OverloadedStrings, MultiParamTypeClasses #-} -- | This module defines the 'RestController' class module Data.IterIO.Http.Support.RestController ( RestController(..) , routeRestController ) where import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import Data.IterIO.Http.Support.Action import Data.IterIO.Http.Support.Routing import Data.IterIO.Http.Support.Responses import Data.Monoid -- |The class @RestController@ allows a set of actions to be routed using -- RESTful HTTP verbs. class Monad m => RestController t b m a where -- |GET \/ restIndex :: a -> Action t b m () restIndex _ = respond404 -- |GET \/:id -- -- @id@ is passed in as the second parameter. restShow :: a -> L.ByteString -> Action t b m () restShow _ _ = respond404 -- |GET \/new restNew :: a -> Action t b m () restNew _ = respond404 -- |POST \/ restCreate :: a -> Action t b m () restCreate _ = respond404 -- |GET \/:id\/edit -- -- @id@ is passed in as the second parameter. restEdit :: a -> L.ByteString -> Action t b m () restEdit _ _ = respond404 -- |PUT \/:id -- -- @id@ is passed in as the second parameter. -- -- Since @PUT@ is not supported by many browsers, this action also responds to -- requests containing the HTTP header "X-HTTP-Method-Override: PUT" -- regardless of the actual HTTP method (@GET@ or @POST@) restUpdate :: a -> L.ByteString -> Action t b m () restUpdate _ _ = respond404 -- |DELETE \/:id -- -- @id@ is passed in as the second parameter. -- -- Since @DELETE@ is not supported by many browsers, this action also responds to -- requests containing the HTTP header "X-HTTP-Method-Override: DELETE" -- regardless of the actual HTTP method (@GET@ or @POST@) restDestroy :: a -> L.ByteString -> Action t b m () restDestroy _ _ = respond404 -- |Runs an action, passing in named parameter. runWithVar :: Monad m => S.ByteString -> (L.ByteString -> Action t b m ()) -> Action t b m () runWithVar varName controller = do (Just var) <- param varName controller $ paramValue var -- |Routes URLs under the given @String@ to actions in a @RestController@. For -- example -- -- @ -- routeRestController "posts" myRestController -- @ -- -- will map the follwoing URLs: -- -- * GET \/posts => myRestController#restIndex -- -- * POST \/posts => myRestController#restCreate -- -- * GET \/posts\/:id => myRestController#restShow -- -- * GET \/posts\/:id\/edit => myRestController#restEdit -- -- * GET \/posts\/:id\/new => myRestController#restNew -- -- * DELETE \/posts\/:id => myRestController#restDestroy -- -- * PUT \/posts\/:id => myRestController#restUpdate -- routeRestController :: RestController t b m a => String -> a -> ActionRoute b m t routeRestController prefix controller = routePattern prefix $ mconcat [ routeTop $ routeMethod "GET" $ routeAction $ restIndex controller , routeTop $ routeMethod "POST" $ routeAction $ restCreate controller , routeMethod "GET" $ routePattern "/new" $ routeAction $ restNew controller , routeMethod "GET" $ routePattern "/:id/edit" $ routeAction $ runWithVar "id" $ restEdit controller , routeMethod "GET" $ routePattern "/:id" $ routeAction $ runWithVar "id" $ restShow controller , routeMethod "DELETE" $ routePattern "/:id" $ routeAction $ runWithVar "id" $ restDestroy controller , routeMethod "PUT" $ routePattern "/:id" $ routeAction $ runWithVar "id" $ restUpdate controller , routeMethod "POST" $ routePattern "/:id" $ routeAction $ runWithVar "id" $ restUpdate controller ]