{-# LANGUAGE TemplateHaskell #-}{-# LANGUAGE CPP #-}{-# LANGUAGE OverloadedStrings #-}moduleYesod.Dispatch(-- * Quasi-quoted routingparseRoutes,parseRoutesNoCheck,parseRoutesFile,parseRoutesFileNoCheck,mkYesod,mkYesodSub-- ** More fine-grained,mkYesodData,mkYesodSubData,mkYesodDispatch,mkYesodSubDispatch-- ** Path pieces,PathPiece(..),PathMultiPiece(..),Texts-- * Convert to WAI,toWaiApp,toWaiAppPlain)whereimportData.Functor((<$>))importPreludehiding(exp)importYesod.Internal.CoreimportYesod.Handlerhiding(lift)importYesod.Widget(GWidget)importWeb.PathPiecesimportLanguage.Haskell.TH.SyntaximportqualifiedNetwork.WaiasWimportNetwork.Wai.Middleware.GzipimportNetwork.Wai.Middleware.AutoheadimportData.ByteString.Lazy.Char8()importWeb.ClientSessionimportData.Text(Text)importData.Text.Encoding(decodeUtf8With)importData.Text.Encoding.Error(lenientDecode)importData.Monoid(mappend)importqualifiedData.ByteStringasSimportqualifiedBlaze.ByteString.BuilderimportNetwork.HTTP.Types(status301)importYesod.Routes.THimportYesod.Content(chooseRep)importYesod.Routes.ParsetypeTexts=[Text]-- | Generates URL datatype and site function for the given 'Resource's. This-- is used for creating sites, /not/ subsites. See 'mkYesodSub' for the latter.-- Use 'parseRoutes' to create the 'Resource's.mkYesod::String-- ^ name of the argument datatype->[ResourceString]->Q[Dec]mkYesodname=fmap(uncurry(++)).mkYesodGeneralname[][]False-- | Generates URL datatype and site function for the given 'Resource's. This-- is used for creating subsites, /not/ sites. See 'mkYesod' for the latter.-- Use 'parseRoutes' to create the 'Resource's. In general, a subsite is not-- executable by itself, but instead provides functionality to-- be embedded in other sites.mkYesodSub::String-- ^ name of the argument datatype->Cxt->[ResourceString]->Q[Dec]mkYesodSubnameclazzes=fmap(uncurry(++)).mkYesodGeneralname'restclazzesTruewhere(name':rest)=wordsname-- | Sometimes, you will want to declare your routes in one file and define-- your handlers elsewhere. For example, this is the only way to break up a-- monolithic file into smaller parts. Use this function, paired with-- 'mkYesodDispatch', to do just that.mkYesodData::String->[ResourceString]->Q[Dec]mkYesodDatanameres=mkYesodDataGeneralname[]FalseresmkYesodSubData::String->Cxt->[ResourceString]->Q[Dec]mkYesodSubDatanameclazzesres=mkYesodDataGeneralnameclazzesTrueresmkYesodDataGeneral::String->Cxt->Bool->[ResourceString]->Q[Dec]mkYesodDataGeneralnameclazzesisSubres=dolet(name':rest)=wordsname(x,_)<-mkYesodGeneralname'restclazzesisSubresletrname=mkName$"resources"++nameeres<-liftreslety=[SigDrname$ListT`AppT`(ConT''Resource`AppT`ConT''String),FunDrname[Clause[](NormalBeres)[]]]return$x++y-- | See 'mkYesodData'.mkYesodDispatch::String->[ResourceString]->Q[Dec]mkYesodDispatchname=fmapsnd.mkYesodGeneralname[][]FalsemkYesodSubDispatch::String->Cxt->[ResourceString]->Q[Dec]mkYesodSubDispatchnameclazzes=fmapsnd.mkYesodGeneralname'restclazzesTruewhere(name':rest)=wordsnamemkYesodGeneral::String-- ^ foundation type->[String]->Cxt-- ^ classes->Bool-- ^ is subsite?->[ResourceString]->Q([Dec],[Dec])mkYesodGeneralnameargsclazzesisSubresS=doletargs'=mapmkNameargsarg=foldlAppT(ConTname')$mapVarTargs'letres=map(fmapparseType)resSrenderRouteDec<-mkRenderRouteInstanceargresdisp<-mkDispatchClause[|yesodRunner|][|yesodDispatch|][|fmapchooseRep|]resletmaster=mkName"master"letctx=ifisSubthenClassP(mkName"Yesod")[VarTmaster]:clazzeselse[]letytyp=ifisSubthenConT''YesodDispatch`AppT`arg`AppT`VarTmasterelseConT''YesodDispatch`AppT`arg`AppT`argletyesodDispatch'=InstanceDctxytyp[FunD(mkName"yesodDispatch")[disp]]return(renderRouteDec:masterTypSyns,[yesodDispatch'])wherename'=mkNamenamemasterTypSyns|isSub=[]|otherwise=[TySynD(mkName"Handler")[](ConT''GHandler`AppT`ConTname'`AppT`ConTname'),TySynD(mkName"Widget")[](ConT''GWidget`AppT`ConTname'`AppT`ConTname'`AppT`TupleT0)]-- | Convert the given argument into a WAI application, executable with any WAI-- handler. This is the same as 'toWaiAppPlain', except it includes two-- middlewares: GZIP compression and autohead. This is the-- recommended approach for most users.toWaiApp::(Yesodmaster,YesodDispatchmastermaster)=>master->IOW.ApplicationtoWaiAppy=gzip(gzipSettingsy).autohead<$>toWaiAppPlainy-- | Convert the given argument into a WAI application, executable with any WAI-- handler. This differs from 'toWaiApp' in that it uses no middlewares.toWaiAppPlain::(Yesodmaster,YesodDispatchmastermaster)=>master->IOW.ApplicationtoWaiAppPlaina=toWaiApp'a<$>encryptKeyatoWaiApp'::(Yesodmaster,YesodDispatchmastermaster)=>master->MaybeKey->W.ApplicationtoWaiApp'ykey'env=casecleanPathy$W.pathInfoenvofLeftpieces->sendRedirectypiecesenvRightpieces->yesodDispatchyyidapp404handler405methodpieceskey'envwhereapp404=yesodRunnernotFoundyyNothingidhandler405route=yesodRunnerbadMethodyy(Justroute)idmethod=decodeUtf8WithlenientDecode$W.requestMethodenvsendRedirect::Yesodmaster=>master->[Text]->W.ApplicationsendRedirectysegments'env=return$W.responseLBSstatus301[("Content-Type","text/plain"),("Location",Blaze.ByteString.Builder.toByteStringdest')]"Redirecting"wheredest=joinPathy(resolveApprootyenv)segments'[]dest'=ifS.null(W.rawQueryStringenv)thendestelse(dest`mappend`Blaze.ByteString.Builder.fromByteString(W.rawQueryStringenv))