{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, ScopedTypeVariables #-} -- | It should be noted that most of the code snippets below depend on the -- OverloadedStrings language pragma. module Web.Scotty ( -- * scotty-to-WAI scotty, scottyApp -- * Defining Middleware and Routes -- -- | 'Middleware' and routes are run in the order in which they -- are defined. All middleware is run first, followed by the first -- route that matches. If no route matches, a 404 response is given. , middleware, get, post, put, delete, addroute -- * Defining Actions -- ** Accessing the Request, Captures, and Query Parameters , request, body, param, jsonData -- ** Modifying the Response and Redirecting , status, header, redirect -- ** Setting Response Body -- -- | Note: only one of these should be present in any given route -- definition, as they completely replace the current 'Response' body. , text, html, file, json -- ** Exceptions , raise, rescue, next -- * Types , ScottyM, ActionM, Parsable ) where import Blaze.ByteString.Builder (fromByteString, fromLazyByteString) import Control.Applicative import Control.Monad.Error import Control.Monad.Reader import qualified Control.Monad.State as MS import Control.Monad.Trans.Resource (ResourceT) import qualified Data.Aeson as A import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.CaseInsensitive as CI import Data.Default (Default, def) import Data.Conduit.Lazy (lazyConsume) import Data.Maybe (fromMaybe) import Data.Monoid (mconcat) import qualified Data.Text.Lazy as T import Data.Text.Lazy.Encoding (encodeUtf8) import Network.HTTP.Types import Network.Wai import Network.Wai.Handler.Warp (Port, run) import Web.Scotty.Util data ScottyState = ScottyState { middlewares :: [Middleware] , routes :: [Middleware] } instance Default ScottyState where def = ScottyState [] [] newtype ScottyM a = S { runS :: MS.StateT ScottyState IO a } deriving (Monad, MonadIO, Functor, MS.MonadState ScottyState) -- | Run a scotty application using the warp server. scotty :: Port -> ScottyM () -> IO () scotty p s = putStrLn "Setting phasers to stun... (ctrl-c to quit)" >> (run p =<< scottyApp s) -- | Turn a scotty application into a WAI 'Application', which can be -- run with any WAI handler. scottyApp :: ScottyM () -> IO Application scottyApp defs = do s <- MS.execStateT (runS defs) def return $ foldl (flip ($)) notFoundApp $ routes s ++ middlewares s notFoundApp :: Application notFoundApp _ = return $ ResponseBuilder status404 [("Content-Type","text/html")] $ fromByteString "