{-# OPTIONS_GHC -fglasgow-exts #-}------------------------------------------------------------------------------- |-- Module : Network.CGI.Monad-- Copyright : (c) Bjorn Bringert 2006-- License : BSD-style---- Maintainer : bjorn@bringert.net-- Stability : experimental-- Portability : non-portable---- Internal stuff that most people shouldn't have to use.-- This module mostly deals with the -- internals of the CGIT monad transformer.-------------------------------------------------------------------------------moduleNetwork.CGI.Monad(-- * CGI monad classMonadCGI(..),-- * CGI monad transformerCGIT(..),CGI,runCGIT,-- * Request infoCGIRequest(..),-- * Error handlingthrowCGI,catchCGI,tryCGI,handleExceptionCGI,)whereimportControl.ExceptionasException(Exception,try,throwIO)importControl.Monad(liftM)importControl.Monad.Error(MonadError(..))importControl.Monad.Reader(ReaderT(..),asks)importControl.Monad.Writer(WriterT(..),tell)importControl.Monad.Trans(MonadTrans,MonadIO,liftIO,lift)importData.Monoid(mempty)importData.Typeable(Typeable(..),Typeable1(..),mkTyConApp,mkTyCon)importNetwork.CGI.Protocol---- * CGIT monad transformer---- | A simple CGI monad with just IO.typeCGIa=CGITIOa-- | The CGIT monad transformer.newtypeCGITma=CGIT{unCGIT::ReaderTCGIRequest(WriterTHeadersm)a}instance(Typeable1m,Typeablea)=>Typeable(CGITma)wheretypeOf_=mkTyConApp(mkTyCon"Network.CGI.Monad.CGIT")[typeOf1(undefined::ma),typeOf(undefined::a)]instanceMonadm=>Functor(CGITm)wherefmapfc=CGIT(fmapf(unCGITc))instanceMonadm=>Monad(CGITm)wherec>>=f=CGIT(unCGITc>>=unCGIT.f)return=CGIT.return-- FIXME: should we have an error monad instead?fail=CGIT.failinstanceMonadIOm=>MonadIO(CGITm)whereliftIO=lift.liftIO-- | The class of CGI monads. Most CGI actions can be run in-- any monad which is an instance of this class, which means that-- you can use your own monad transformers to add extra functionality.classMonadm=>MonadCGImwhere-- | Add a response header.cgiAddHeader::HeaderName->String->m()-- | Get something from the CGI request.cgiGet::(CGIRequest->a)->mainstanceMonadm=>MonadCGI(CGITm)wherecgiAddHeadernv=CGIT$lift$tell[(n,v)]cgiGet=CGIT.asksinstanceMonadTransCGITwherelift=CGIT.lift.lift-- | Run a CGI action.runCGIT::Monadm=>CGITma->CGIRequest->m(Headers,a)runCGIT(CGITc)=liftM(uncurry(flip(,))).runWriterT.runReaderTc---- * Error handling--instanceMonadErrorException(CGITIO)wherethrowError=throwCGIcatchError=catchCGI-- | Throw an exception in a CGI monad. The monad is required to be-- a 'MonadIO', so that we can use 'throwIO' to guarantee ordering.throwCGI::(MonadCGIm,MonadIOm)=>Exception->mathrowCGI=liftIO.throwIO-- | Catches any expection thrown by a CGI action, and uses the given -- exception handler if an exception is thrown.catchCGI::CGIa->(Exception->CGIa)->CGIacatchCGIch=tryCGIc>>=eitherhreturn-- | Catches any exception thrown by an CGI action, and returns either-- the exception, or if no exception was raised, the result of the action.tryCGI::CGIa->CGI(EitherExceptiona)tryCGI(CGITc)=CGIT(ReaderT(\r->WriterT(f(runWriterT(runReaderTcr)))))wheref=liftM(either(\ex->(Leftex,mempty))(\(a,w)->(Righta,w))).try{-# DEPRECATED handleExceptionCGI "Use catchCGI instead." #-}-- | Deprecated version of 'catchCGI'. Use 'catchCGI' instead.handleExceptionCGI::CGIa->(Exception->CGIa)->CGIahandleExceptionCGI=catchCGI