packages feed

haskoon 0.1 → 0.3.1.1

raw patch · 12 files changed

+374/−189 lines, 12 filesdep ~basedep ~fastcgidep ~hsloggernew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, fastcgi, hslogger

API changes (from Hackage documentation)

- Factis.Haskoon.Web: checkMethod :: (RqAccess m) => (String -> Bool) -> m String
- Factis.Haskoon.Web: class (MonadPlus m) => RqAccess m
- Factis.Haskoon.Web: cookie :: (RqAccess m) => String -> m String
- Factis.Haskoon.Web: header :: (RqAccess m) => String -> m String
- Factis.Haskoon.Web: param :: (RqAccess m) => String -> m String
- Factis.Haskoon.Web: repl :: (RqAccess m) => Int -> m String
- Factis.Haskoon.WebRqAccessM: RqAccessM :: (RqRead a) -> RqAccessM a
- Factis.Haskoon.WebRqAccessM: RqData :: String -> [(String, String)] -> [(String, String)] -> [String] -> [(String, String)] -> RqData
- Factis.Haskoon.WebRqAccessM: checkMethod :: (RqAccess m) => (String -> Bool) -> m String
- Factis.Haskoon.WebRqAccessM: class (MonadPlus m) => RqAccess m
- Factis.Haskoon.WebRqAccessM: cookie :: (RqAccess m) => String -> m String
- Factis.Haskoon.WebRqAccessM: data RqData
- Factis.Haskoon.WebRqAccessM: header :: (RqAccess m) => String -> m String
- Factis.Haskoon.WebRqAccessM: instance Monad RqAccessM
- Factis.Haskoon.WebRqAccessM: instance MonadPlus RqAccessM
- Factis.Haskoon.WebRqAccessM: instance RqAccess RqAccessM
- Factis.Haskoon.WebRqAccessM: newtype RqAccessM a
- Factis.Haskoon.WebRqAccessM: param :: (RqAccess m) => String -> m String
- Factis.Haskoon.WebRqAccessM: repl :: (RqAccess m) => Int -> m String
- Factis.Haskoon.WebRqAccessM: rqd_cookies :: RqData -> [(String, String)]
- Factis.Haskoon.WebRqAccessM: rqd_headers :: RqData -> [(String, String)]
- Factis.Haskoon.WebRqAccessM: rqd_method :: RqData -> String
- Factis.Haskoon.WebRqAccessM: rqd_params :: RqData -> [(String, String)]
- Factis.Haskoon.WebRqAccessM: rqd_repls :: RqData -> [String]
- Factis.Haskoon.WebRqAccessM: runRqAccessM :: RqAccessM t -> RqData -> Either String t
+ Factis.Haskoon.RqAccess: checkMethod :: (RqAccess m) => (String -> Bool) -> m String
+ Factis.Haskoon.RqAccess: class FromRq a
+ Factis.Haskoon.RqAccess: class (MonadPlus m) => RqAccess m
+ Factis.Haskoon.RqAccess: cookie :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccess: fromRq :: (FromRq a, RqAccess m) => m a
+ Factis.Haskoon.RqAccess: header :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccess: param :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccess: repl :: (RqAccess m) => Int -> m String
+ Factis.Haskoon.RqAccessM: RqAccessM :: (RqRead a) -> RqAccessM a
+ Factis.Haskoon.RqAccessM: RqData :: String -> [(String, String)] -> [(String, String)] -> [String] -> [(String, String)] -> RqData
+ Factis.Haskoon.RqAccessM: checkMethod :: (RqAccess m) => (String -> Bool) -> m String
+ Factis.Haskoon.RqAccessM: class (MonadPlus m) => RqAccess m
+ Factis.Haskoon.RqAccessM: cookie :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccessM: data RqData
+ Factis.Haskoon.RqAccessM: header :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccessM: instance Monad RqAccessM
+ Factis.Haskoon.RqAccessM: instance MonadPlus RqAccessM
+ Factis.Haskoon.RqAccessM: instance RqAccess RqAccessM
+ Factis.Haskoon.RqAccessM: newtype RqAccessM a
+ Factis.Haskoon.RqAccessM: param :: (RqAccess m) => String -> m String
+ Factis.Haskoon.RqAccessM: repl :: (RqAccess m) => Int -> m String
+ Factis.Haskoon.RqAccessM: rqd_cookies :: RqData -> [(String, String)]
+ Factis.Haskoon.RqAccessM: rqd_headers :: RqData -> [(String, String)]
+ Factis.Haskoon.RqAccessM: rqd_method :: RqData -> String
+ Factis.Haskoon.RqAccessM: rqd_params :: RqData -> [(String, String)]
+ Factis.Haskoon.RqAccessM: rqd_repls :: RqData -> [String]
+ Factis.Haskoon.RqAccessM: runRqAccessM :: RqAccessM t -> RqData -> Either String t
+ Factis.Haskoon.Web: WebRec :: m FilePath -> m URI -> m URI -> m String -> m String -> m ByteString -> m WebParams -> m WebHeaders -> m WebCookies -> (Int -> Maybe String -> m ()) -> (ByteString -> m (WebRes m)) -> (String -> String -> m ()) -> (Cookie -> m ()) -> (Cookie -> m ()) -> (String -> Priority -> String -> m ()) -> m [String] -> (forall a. String -> m a) -> (forall a. [String] -> m a -> m a) -> WebRec m
+ Factis.Haskoon.Web: data WebRec m
+ Factis.Haskoon.Web: webRec :: (Web m) => WebRec m
+ Factis.Haskoon.Web: web_containerUri :: WebRec m -> m URI
+ Factis.Haskoon.Web: web_documentRoot :: WebRec m -> m FilePath
+ Factis.Haskoon.Web: web_fail :: WebRec m -> forall a. String -> m a
+ Factis.Haskoon.Web: web_getBody :: WebRec m -> m ByteString
+ Factis.Haskoon.Web: web_getCookies :: WebRec m -> m WebCookies
+ Factis.Haskoon.Web: web_getHeaders :: WebRec m -> m WebHeaders
+ Factis.Haskoon.Web: web_getParams :: WebRec m -> m WebParams
+ Factis.Haskoon.Web: web_getRepls :: WebRec m -> m [String]
+ Factis.Haskoon.Web: web_log :: WebRec m -> String -> Priority -> String -> m ()
+ Factis.Haskoon.Web: web_method :: WebRec m -> m String
+ Factis.Haskoon.Web: web_pathInfo :: WebRec m -> m String
+ Factis.Haskoon.Web: web_requestUri :: WebRec m -> m URI
+ Factis.Haskoon.Web: web_sendBSL :: WebRec m -> ByteString -> m (WebRes m)
+ Factis.Haskoon.Web: web_setCookie :: WebRec m -> Cookie -> m ()
+ Factis.Haskoon.Web: web_setHeader :: WebRec m -> String -> String -> m ()
+ Factis.Haskoon.Web: web_setStatus :: WebRec m -> Int -> Maybe String -> m ()
+ Factis.Haskoon.Web: web_unsetCookie :: WebRec m -> Cookie -> m ()
+ Factis.Haskoon.Web: web_withRepls :: WebRec m -> forall a. [String] -> m a -> m a
+ Factis.Haskoon.WebHelper: statusCodeMessageMap :: [(Int, String)]
+ Factis.Haskoon.WebIdT: WebIdT :: m a -> WebIdT m a
+ Factis.Haskoon.WebIdT: class (MonadTrans t) => WebTrans t
+ Factis.Haskoon.WebIdT: instance (Monad m) => Monad (WebIdT m)
+ Factis.Haskoon.WebIdT: instance (MonadIO m) => MonadIO (WebIdT m)
+ Factis.Haskoon.WebIdT: instance MonadTrans WebIdT
+ Factis.Haskoon.WebIdT: instance WebTrans WebIdT
+ Factis.Haskoon.WebIdT: liftWeb :: (WebTrans t, Web m) => m a -> t m a
+ Factis.Haskoon.WebIdT: liftWebFun :: (WebTrans t, Web m) => (forall a. m a -> m a) -> t m b -> t m b
+ Factis.Haskoon.WebIdT: newtype WebIdT m a
+ Factis.Haskoon.WebIdT: runWebIdT :: WebIdT m a -> m a
+ Factis.Haskoon.WebReaderT: data WebReaderT r m a
+ Factis.Haskoon.WebReaderT: instance (Monad m) => Monad (WebReaderT r m)
+ Factis.Haskoon.WebReaderT: instance (Monad m) => MonadReader r (WebReaderT r m)
+ Factis.Haskoon.WebReaderT: instance (MonadIO m) => MonadIO (WebReaderT r m)
+ Factis.Haskoon.WebReaderT: instance (Web m) => Web (WebReaderT r m)
+ Factis.Haskoon.WebReaderT: instance MonadTrans (WebReaderT r)
+ Factis.Haskoon.WebReaderT: instance WebTrans (WebReaderT r)
+ Factis.Haskoon.WebReaderT: runWebReaderT :: (Monad m) => WebReaderT r m a -> r -> m a
+ Factis.Haskoon.WebSitemap: instance WebTrans SitemapT
+ Factis.Haskoon.WebTrans: class (MonadTrans t) => WebTrans t
+ Factis.Haskoon.WebTrans: liftWeb :: (WebTrans t, Web m) => m a -> t m a
+ Factis.Haskoon.WebTrans: liftWebFun :: (WebTrans t, Web m) => (forall a. m a -> m a) -> t m b -> t m b
+ Factis.Haskoon.WebTrans: liftWebRec :: (Web m, WebTrans t) => (m (WebRes m) -> m (WebRes (t m))) -> WebRec m -> WebRec (t m)
- Factis.Haskoon.Web: class (Monad m) => Web m where { type family WebRes m; { webGetParam n = liftM (lookup n) webGetParams webGetHeader n = liftM lookup webGetHeaders where lookup = fmap snd . find ((== map toLower n) . map toLower . fst) webSendError status msg = do { webSetStatus status Nothing; webSetHeader "Content-Type" "text/plain; charset=UTF-8"; webSendBSL (fromString msg) } } }
+ Factis.Haskoon.Web: class (Monad m) => Web m where { type family WebRes m; { webGetParam n = liftM (lookup n) webGetParams webGetHeader n = liftM lookup' webGetHeaders where lookup' = fmap snd . find ((== map toLower n) . map toLower . fst) webSendError status msg = do { webSetStatus status Nothing; webSetHeader "Content-Type" "text/plain; charset=UTF-8"; webSendBSL (fromString msg) } webRunFromRq = do { meth <- webMethod; headers <- webGetHeaders; repls <- webGetRepls; params <- webGetParams; cookies <- webGetCookies; let rqdata = RqData meth params headers repls cookies; return (runRqAccessM fromRq rqdata) } webFail = web_fail webRec webWithRepls = web_withRepls webRec webGetRepls = web_getRepls webRec webLog = web_log webRec webUnsetCookie = web_unsetCookie webRec webSetCookie = web_setCookie webRec webSetHeader = web_setHeader webRec webSendBSL = web_sendBSL webRec webSetStatus = web_setStatus webRec webGetCookies = web_getCookies webRec webGetHeaders = web_getHeaders webRec webGetParams = web_getParams webRec webGetBody = web_getBody webRec webMethod = web_method webRec webPathInfo = web_pathInfo webRec webRequestUri = web_requestUri webRec webContainerUri = web_containerUri webRec webDocumentRoot = web_documentRoot webRec webRec = WebRec webDocumentRoot webContainerUri webRequestUri webPathInfo webMethod webGetBody webGetParams webGetHeaders webGetCookies webSetStatus webSendBSL webSetHeader webSetCookie webUnsetCookie webLog webGetRepls webFail webWithRepls } }
- Factis.Haskoon.Web: webGetCookies :: (Web m) => m [(String, String)]
+ Factis.Haskoon.Web: webGetCookies :: (Web m) => m WebCookies
- Factis.Haskoon.Web: webGetHeaders :: (Web m) => m [(String, String)]
+ Factis.Haskoon.Web: webGetHeaders :: (Web m) => m WebHeaders
- Factis.Haskoon.Web: webGetParams :: (Web m) => m [(String, String)]
+ Factis.Haskoon.Web: webGetParams :: (Web m) => m WebParams

Files

haskoon.cabal view
@@ -1,5 +1,6 @@+--*- coding: utf-8 -*-- Name:                haskoon-Version:             0.1+Version:             0.3.1.1 Synopsis:            Web Application Abstraction Description:         Web Astraction Layer with a binding to CGI providing a simple way to                      map parameter and header values to data structures (inspired by HAppS)@@ -7,19 +8,28 @@ License:             LGPL License-file:        LICENSE Category:            Web-Author:              David Leuschner, Dirk Spöri-Maintainer:          David Leuschner <leuschner@openfactis.org>+Author:              David Leuschner <leuschner@factisresearch.com>, Dirk Spöri <spoeri@factisresearch.com>, Stefan Wehr <wehr@factisresearch.com>+Maintainer:          David Leuschner <leuschner@factisresearch.com>, Dirk Spöri <spoeri@factisresearch.com>, Stefan Wehr <wehr@factisresearch.com> Build-Type:          Simple Cabal-Version:       >= 1.2  Library   Hs-Source-Dirs:    src-  GHC-Options: -Wall-  Build-Depends:     base >= 3 && < 4, bytestring, utf8-string, hslogger, regex-posix,-                     MissingH, directory, filepath, mtl, safe, MaybeT, fastcgi,+  GHC-Options: -Wall -fno-warn-orphans+  Build-Depends:     base >= 4 && < 5, bytestring, utf8-string, hslogger >= 1.1.0, regex-posix,+                     MissingH, directory, filepath, mtl, safe, MaybeT,                      cgi, network, hsp, hsx+  if impl(ghc < 6.12)+    Build-Depends:   fastcgi == 3001.0.2.2+  else+    Build-Depends:   fastcgi   Exposed-Modules:   Factis.Haskoon.Web                      Factis.Haskoon.WebSitemap                      Factis.Haskoon.WebCGI-                     Factis.Haskoon.WebRqAccessM+                     Factis.Haskoon.RqAccess+                     Factis.Haskoon.RqAccessM                      Factis.Haskoon.WebHsp+                     Factis.Haskoon.WebHelper+                     Factis.Haskoon.WebTrans+                     Factis.Haskoon.WebIdT+                     Factis.Haskoon.WebReaderT
+ src/Factis/Haskoon/RqAccess.hs view
@@ -0,0 +1,14 @@+module Factis.Haskoon.RqAccess (RqAccess(..), FromRq(..)) where++import Control.Monad (MonadPlus)+import Control.Monad.Error ()++class MonadPlus m => RqAccess m where+    param :: String -> m String+    header :: String -> m String+    repl :: Int -> m String+    cookie :: String -> m String+    checkMethod :: (String -> Bool) -> m String++class FromRq a where+    fromRq :: RqAccess m => m a
+ src/Factis/Haskoon/RqAccessM.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Factis.Haskoon.RqAccessM+    (RqData(..), RqAccess(..), RqAccessM(..), runRqAccessM)+where++----------------------------------------+-- STDLIB+----------------------------------------+import Control.Monad (MonadPlus)+import Control.Monad.Reader (ReaderT(runReaderT),asks)++----------------------------------------+-- SITE-PACKAGES+----------------------------------------+import Safe (atMay)++----------------------------------------+-- LOCAL+----------------------------------------+import Factis.Haskoon.RqAccess (RqAccess(..))++data RqData = RqData { rqd_method :: String+                     , rqd_params :: [(String,String)]+                     , rqd_headers :: [(String,String)]+                     , rqd_repls :: [String]+                     , rqd_cookies :: [(String, String)]+                     }++type RqRead a = ReaderT RqData (Either String) a++newtype RqAccessM a = RqAccessM (RqRead a) deriving (Monad, MonadPlus)+++instance RqAccess RqAccessM where+    param n = RqAccessM (readFromPairs rqd_params n "Parameter")+    repl i = RqAccessM (readFromRqData rqd_repls (flip atMay i) desc)+        where desc = "Replacement "++show i+    cookie n = RqAccessM (readFromPairs rqd_cookies n "Cookie")+    header n = RqAccessM (readFromPairs rqd_headers n "Header")+    checkMethod isMethOk =+        RqAccessM $+        do meth <- asks rqd_method+           if isMethOk meth+             then return meth+             else fail $ "Invalid request method `"++meth++"'."++readFromPairs :: (Eq a,Show a) => (RqData -> [(a,b)]) -> a -> String -> RqRead b+readFromPairs rqd_pairs key name = readFromRqData rqd_pairs findIn desc+    where findIn = lookup key+          desc = name ++ " `"++show key++"'"++readFromRqData :: (RqData -> a) -> (a -> Maybe b) -> String -> RqRead b+readFromRqData rqd_value findIn desc =+    do value <- asks rqd_value+       case findIn value of+         Nothing -> fail $ desc ++ " not found."+         Just v -> return v++runRqAccessM :: RqAccessM t -> RqData -> Either String t+runRqAccessM (RqAccessM r) d = runReaderT r d
src/Factis/Haskoon/Web.hs view
@@ -4,18 +4,16 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE Rank2Types #-}  module Factis.Haskoon.Web-    (Web,WebRes,WebIO,RqAccess(..),FromRq(..),ToWebRes(..), WebWebRes-    ,webDocumentRoot,webContainerUri,webRequestUri,webPathInfo,webMethod-    ,webGetBody,webGetParams,webGetHeaders,webGetCookies,webSetStatus-    ,webSendBSL,webFail,webSetHeader,webUnsetCookie,webGetRepls-    ,webWithRepls,webRunFromRq,webLog,webSendError,webGetHeader-    ,webGetParam,webRepl,webOk,webNotFound,webFileNotFound,webBadRequest+    (Web(..),WebIO,FromRq(..),ToWebRes(..), WebWebRes, WebRec(..)+    ,webRepl,webOk,webNotFound,webFileNotFound,webBadRequest     ,webSendString,webGetCookie,webRedirect,webWithData,webCheckData-    ,webSendFile, webSetCookie, notEmpty, optional+    ,webSendFile, notEmpty, optional     ,webLogNotice,webLogTrace,webLogDebug     ,Cookie(..), newCookie, findCookie, deleteCookie, showCookie, readCookies+    , ) where  ----------------------------------------@@ -25,7 +23,6 @@ import Control.Monad.Trans (MonadIO,liftIO)  import Data.Char (toLower)-import Data.Maybe (listToMaybe, catMaybes) import Data.List (find, isSuffixOf)  import System.FilePath.Posix ((</>))@@ -34,9 +31,7 @@ ---------------------------------------- -- SITE-PACKAGES -----------------------------------------import System.Log.Logger (getRootLogger, saveGlobalLogger, setLevel, addHandler-                         ,Priority(..), noticeM)-import System.Log.Handler.Syslog (openlog,Facility(..))+import System.Log.Logger (Priority(..))  import qualified Data.ByteString.Lazy.UTF8 as BSLU import qualified Data.ByteString.Lazy as BSL@@ -45,40 +40,109 @@ import Network.CGI.Cookie (Cookie(..), newCookie, findCookie, deleteCookie                           ,showCookie, readCookies) +----------------------------------------+-- LOCAL+----------------------------------------+import Factis.Haskoon.RqAccess (FromRq(..))+import Factis.Haskoon.RqAccessM (RqData(..), runRqAccessM)++type WebParams = [(String,String)]+type WebHeaders = [(String,String)]+type WebCookies = [(String,String)]++data WebRec m+    = WebRec+    { web_documentRoot :: m FilePath+    , web_containerUri :: m URI+    , web_requestUri :: m URI+    , web_pathInfo :: m String+    , web_method :: m String+    , web_getBody :: m BSL.ByteString+    , web_getParams :: m WebParams+    , web_getHeaders :: m WebHeaders+    , web_getCookies :: m WebCookies+    , web_setStatus :: Int -> Maybe String -> m ()+    , web_sendBSL :: BSL.ByteString -> m (WebRes m)+    , web_setHeader :: String -> String -> m ()+    , web_setCookie :: Cookie -> m ()+    , web_unsetCookie :: Cookie -> m ()+    , web_log :: String -> Priority -> String -> m ()+    , web_getRepls :: m [String]+    , web_fail :: forall a. String -> m a+    , web_withRepls :: forall a. [String] -> m a -> m a+    }++-- | You may either define @webRec@ or all of @webDocumentRoot@,+-- @webContainerUri@, @webPathInfo@, @webMethod@, @webGetBody@,+-- @webGetParams@, @webGetHeaders@, @webGetCookies@, @webSetStatus@,+-- @webSendBSL@, @webSetHeader@, @webSetCookie@, @webUnsetCookie@,+-- @webLog@ and @webGetRepls@, @webWithRepls@ and @webFail@. class Monad m => Web m where     type WebRes m+    -- record-based implementation of most instance methods+    webRec :: WebRec m+    webRec = WebRec webDocumentRoot webContainerUri webRequestUri webPathInfo webMethod+                       webGetBody webGetParams webGetHeaders webGetCookies webSetStatus+                       webSendBSL webSetHeader webSetCookie webUnsetCookie webLog+                       webGetRepls webFail webWithRepls     -- general     webDocumentRoot :: m FilePath+    webDocumentRoot = web_documentRoot webRec     webContainerUri :: m URI+    webContainerUri = web_containerUri webRec     -- request     webRequestUri :: m URI+    webRequestUri = web_requestUri webRec     webPathInfo :: m String+    webPathInfo = web_pathInfo webRec     webMethod :: m String+    webMethod = web_method webRec     webGetBody :: m BSL.ByteString-    webGetParams :: m [(String,String)]-    webGetHeaders :: m [(String,String)]-    webGetCookies :: m [(String,String)]+    webGetBody = web_getBody webRec+    webGetParams :: m WebParams+    webGetParams = web_getParams webRec+    webGetHeaders :: m WebHeaders+    webGetHeaders = web_getHeaders webRec+    webGetCookies :: m WebCookies+    webGetCookies = web_getCookies webRec     -- response     webSetStatus :: Int -> Maybe String -> m ()+    webSetStatus = web_setStatus webRec     webSendBSL :: BSL.ByteString -> m (WebRes m)+    webSendBSL = web_sendBSL webRec     webSetHeader :: String -> String -> m ()-    webFail :: String -> m a+    webSetHeader = web_setHeader webRec     webSetCookie :: Cookie -> m ()+    webSetCookie = web_setCookie webRec     webUnsetCookie :: Cookie -> m ()-    -- request processing+    webUnsetCookie = web_unsetCookie webRec+    -- special control methods+    webLog :: String -> Priority -> String -> m ()+    webLog = web_log webRec     webGetRepls :: m [String]+    webGetRepls = web_getRepls webRec     webWithRepls :: [String] -> m a -> m a-    webRunFromRq :: FromRq a => m (Either String a)-    webLog :: String -> Priority -> String -> m ()+    webWithRepls = web_withRepls webRec     -- default methods that may be overridden+    webFail :: String -> m a+    webFail = web_fail webRec+    webRunFromRq :: FromRq a => m (Either String a)+    webRunFromRq =+        do meth <- webMethod+           headers <- webGetHeaders+           repls <- webGetRepls+           params <- webGetParams+           cookies <- webGetCookies+           let rqdata = RqData meth params headers repls cookies+           return (runRqAccessM fromRq rqdata)     webSendError :: Int -> String -> m (WebRes m)     webSendError status msg =         do webSetStatus status Nothing            webSetHeader "Content-Type" "text/plain; charset=UTF-8"            webSendBSL (BSLU.fromString msg)     webGetHeader :: String -> m (Maybe String)-    webGetHeader n = liftM lookup  webGetHeaders-        where lookup = fmap snd . find ((==map toLower n) . map toLower . fst)+    webGetHeader n = liftM lookup'  webGetHeaders+        where lookup' = fmap snd . find ((==map toLower n) . map toLower . fst)     webGetParam :: String -> m (Maybe String)     webGetParam n = liftM (lookup n) webGetParams @@ -90,8 +154,13 @@ webOk :: (Web m, ToWebRes a) => a -> m (WebRes m) webOk = toWebRes +webNotFound :: Web m => [Char] -> m (WebRes m) webNotFound name = webSendError 404 ("Not found: " ++ name)++webFileNotFound :: Web m => [Char] -> m (WebRes m) webFileNotFound fpath = webSendError 404 ("File not found: " ++ fpath)++webBadRequest :: Web m => [Char] -> m (WebRes m) webBadRequest msg = webSendError 401 ("Bad Request: " ++ msg)  webSendString :: Web m => String -> m (WebRes m)@@ -107,22 +176,16 @@        webSetStatus (if temp then 302 else 301) Nothing        webSendBSL (BSLU.fromString $ "Redirecting to "++url++".") +_LOGNAME_ :: [Char] _LOGNAME_ = "Web"++webLogNotice, webLogDebug, webLogTrace :: Web m => String -> m () webLogNotice = webLog _LOGNAME_ NOTICE webLogDebug = webLog _LOGNAME_ INFO webLogTrace = webLog _LOGNAME_ DEBUG  class (MonadIO m, Web m) => WebIO m -class MonadPlus m => RqAccess m where-    param :: String -> m String-    header :: String -> m String-    repl :: Int -> m String-    cookie :: String -> m String-    checkMethod :: (String -> Bool) -> m String--class FromRq a where-    fromRq :: RqAccess m => m a  notEmpty :: Monad m => m String -> m String notEmpty m =  m >>= \x -> if x == "" then fail "empty string" else return x
src/Factis/Haskoon/WebCGI.hs view
@@ -12,7 +12,7 @@ import Control.Concurrent (forkIO) import Control.Monad (MonadPlus, liftM, mplus) import Control.Monad.Trans (MonadTrans(lift))-import Control.Monad.Reader (MonadReader(ask,local),ReaderT(runReaderT),asks)+import Control.Monad.Reader (MonadReader(local),ReaderT(runReaderT),asks) import Control.Monad.Error (ErrorT(..), throwError)  import Data.Char (toLower)@@ -22,9 +22,9 @@ ---------------------------------------- -- SITE-PACKAGES -----------------------------------------import Network.CGI.Monad (MonadCGI(..), CGIT)-import Network.CGI.Cookie (readCookies)+import Network.CGI.Monad (MonadCGI(..)) import Network.CGI as CGI+import Network.URI (parseRelativeReference) import Network.FastCGI (runFastCGIConcurrent')  import System.Log.Logger (getRootLogger, saveGlobalLogger, setLevel, addHandler@@ -39,7 +39,7 @@ -- LOCAL ---------------------------------------- import Factis.Haskoon.Web-import Factis.Haskoon.WebRqAccessM+import Factis.Haskoon.WebHelper  data WebData = WebData { webd_repls :: [String] } @@ -49,10 +49,11 @@ newtype WebCGI m a = WebCGI { unWebCGI :: ReaderT WebData (ErrorT String m) a}     deriving (Monad, MonadIO) +inWebCGI :: ReaderT WebData (ErrorT String m) a -> WebCGI m a inWebCGI x = WebCGI x  liftCGI :: (MonadIO m, MonadCGI m) =>-           (forall m. (MonadIO m, MonadCGI m) => m a)+           (forall m'. (MonadIO m', MonadCGI m') => m' a)         -> WebCGI m a liftCGI cgi = inWebCGI (lift (lift cgi)) @@ -76,7 +77,7 @@                  do inputs <- CGI.getInputs                     let body = CGI.formEncode inputs                     return (BSLChar.pack body)-             Just (ContentType "multipart" "form-data" ps) -> fail msg+             Just (ContentType "multipart" "form-data" _ps) -> fail msg              _ -> CGI.getBodyFPS         where           msg = "Content-Type multipart/form-data not supported by WebCGI."@@ -91,26 +92,26 @@            return hs     webGetRepls =  inWebCGI (asks webd_repls)     webWithRepls r (WebCGI cont) = inWebCGI (local (webd_repls_set r) cont)-    webRunFromRq =-        do meth <- webMethod-           headers <- webGetHeaders-           repls <- webGetRepls-           params <- webGetParams-           cookies <- webGetCookies-           let rqdata = RqData meth params headers repls cookies-           return (runRqAccessM fromRq rqdata)     webFail msg = inWebCGI (throwError msg)     webDocumentRoot =         do mdocroot <- liftCGI (CGI.getVar "DOCUMENT_ROOT")            case mdocroot of              Nothing -> webFail "CGI variable `DOCUMENT_ROOT' not set."              Just value -> return value-    webRequestUri = liftCGI CGI.requestURI+    webRequestUri =+        liftCGI $+        do let varname = "REDIRECT_REQUEST_URI"+           mreq <- liftM (>>= parseRelativeReference) $ getVar varname+           case mreq of+             Just req -> return req+             Nothing ->+                 do reqUri <- CGI.requestURI+                    return reqUri     webContainerUri = liftCGI CGI.progURI     webGetCookies = liftCGI (liftM parseVar (CGI.getVar "HTTP_COOKIE"))         where parseVar = readCookies . fromMaybe ""-    webSetCookie cookie = liftCGI (CGI.setCookie cookie)-    webUnsetCookie cookie = liftCGI (CGI.deleteCookie cookie)+    webSetCookie aCookie = liftCGI (CGI.setCookie aCookie)+    webUnsetCookie aCookie = liftCGI (CGI.deleteCookie aCookie)     webMethod = liftCGI CGI.requestMethod     webSetStatus code mmsg = liftCGI (CGI.setStatus code $ fromMaybe "n/a" msg)         where msg = mmsg `mplus` lookup code statusCodeMessageMap@@ -121,6 +122,7 @@  instance (MonadCGI m, MonadIO m) => WebIO (WebCGI m) +initialWebData :: WebData initialWebData = WebData []  runWebCGI :: (MonadCGI m, MonadIO m) => WebCGI m a -> m (Either String a)@@ -152,49 +154,6 @@        logM name NOTICE (name ++ " FastCGI process started.")        runFastCGIConcurrent' forkIO 10 cgi -statusCodeMessageMap :: [(Int, String)]-statusCodeMessageMap =-    [(100, "Continue")-    ,(101, "Switching Protocols")-    ,(200, "OK")-    ,(201, "Created")-    ,(202, "Accepted")-    ,(203, "Non-Authoritative Information")-    ,(204, "No Content")-    ,(205, "Reset Content")-    ,(206, "Partial Content")-    ,(300, "Multiple Choices")-    ,(301, "Moved Permanently")-    ,(302, "Found")-    ,(303, "See Other")-    ,(304, "Not Modified")-    ,(305, "Use Proxy")-    ,(307, "Temporary Redirect")-    ,(400, "Bad Request")-    ,(401, "Unauthorized")-    ,(402, "Payment Required")-    ,(403, "Forbidden")-    ,(404, "Not Found")-    ,(405, "Method Not Allowed")-    ,(406, "Not Acceptable")-    ,(407, "Proxy Authentication Required")-    ,(408, "Request Time-out")-    ,(409, "Conflict")-    ,(410, "Gone")-    ,(411, "Length Required")-    ,(412, "Precondition Failed")-    ,(413, "Request Entity Too Large")-    ,(414, "Request-URI Too Large")-    ,(415, "Unsupported Media Type")-    ,(416, "Requested range not satisfiable")-    ,(417, "Expectation Failed")-    ,(500, "Internal Server Error")-    ,(501, "Not Implemented")-    ,(502, "Bad Gateway")-    ,(503, "Service Unavailable")-    ,(504, "Gateway Time-out")-    ,(505, "HTTP Version not supported")-    ]  replaceCh :: Char -> Char -> String -> String replaceCh from to s = map replChar s
+ src/Factis/Haskoon/WebHelper.hs view
@@ -0,0 +1,45 @@+module Factis.Haskoon.WebHelper (statusCodeMessageMap) where++statusCodeMessageMap :: [(Int, String)]+statusCodeMessageMap =+    [(100, "Continue")+    ,(101, "Switching Protocols")+    ,(200, "OK")+    ,(201, "Created")+    ,(202, "Accepted")+    ,(203, "Non-Authoritative Information")+    ,(204, "No Content")+    ,(205, "Reset Content")+    ,(206, "Partial Content")+    ,(300, "Multiple Choices")+    ,(301, "Moved Permanently")+    ,(302, "Found")+    ,(303, "See Other")+    ,(304, "Not Modified")+    ,(305, "Use Proxy")+    ,(307, "Temporary Redirect")+    ,(400, "Bad Request")+    ,(401, "Unauthorized")+    ,(402, "Payment Required")+    ,(403, "Forbidden")+    ,(404, "Not Found")+    ,(405, "Method Not Allowed")+    ,(406, "Not Acceptable")+    ,(407, "Proxy Authentication Required")+    ,(408, "Request Time-out")+    ,(409, "Conflict")+    ,(410, "Gone")+    ,(411, "Length Required")+    ,(412, "Precondition Failed")+    ,(413, "Request Entity Too Large")+    ,(414, "Request-URI Too Large")+    ,(415, "Unsupported Media Type")+    ,(416, "Requested range not satisfiable")+    ,(417, "Expectation Failed")+    ,(500, "Internal Server Error")+    ,(501, "Not Implemented")+    ,(502, "Bad Gateway")+    ,(503, "Service Unavailable")+    ,(504, "Gateway Time-out")+    ,(505, "HTTP Version not supported")+    ]
src/Factis/Haskoon/WebHsp.hs view
@@ -16,7 +16,7 @@  import qualified HSP import HSP (HSPT, XML)-import HSX.XMLGenerator (Child,asChild,genElement,genEElement,asAttr,Attr((:=)))+import HSX.XMLGenerator (Child,asChild,genElement,genEElement,asAttr,Attr)  ---------------------------------------- -- HASKOON@@ -29,7 +29,7 @@  webHspHtml :: WebIO m => HSPT m XML -> m (WebRes m) webHspHtml page =-    do let env = undefined+    do let env = error "webHspHtml: undefined"        (_, xml) <- HSP.runHSPT HSP.html4Strict page env        webSetHeader "Content-Type" "text/html; charset=UTF-8"        webSendBSL (BSLU.fromString (HSP.renderAsHTML xml))
+ src/Factis/Haskoon/WebIdT.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Factis.Haskoon.WebIdT (WebTrans(..), WebIdT(..)) where++----------------------------------------+-- STDLIB+----------------------------------------+import Control.Monad.Trans (MonadTrans(..), MonadIO(..))++----------------------------------------+-- LOCAL+----------------------------------------+import Factis.Haskoon.WebTrans (WebTrans(..))++newtype WebIdT m a = WebIdT { runWebIdT :: m a } deriving (Monad)++instance MonadTrans WebIdT where+    lift = WebIdT++instance MonadIO m => MonadIO (WebIdT m) where+    liftIO = WebIdT . liftIO++instance WebTrans WebIdT where+    liftWeb = WebIdT+    liftWebFun f cont = WebIdT (f (runWebIdT cont))
+ src/Factis/Haskoon/WebReaderT.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FunctionalDependencies #-}+module Factis.Haskoon.WebReaderT (WebReaderT, runWebReaderT) where++----------------------------------------+-- STDLIB+----------------------------------------+import Control.Monad (liftM)+import Control.Monad.Trans (MonadTrans, MonadIO, lift)+import Control.Monad.Reader (MonadReader, ReaderT, runReaderT, local, ask)++----------------------------------------+-- LOCAL+----------------------------------------+import Factis.Haskoon.Web (Web(..))+import Factis.Haskoon.WebTrans (WebTrans(..), liftWebRec)++newtype WebReaderT r m a = WebReaderT (ReaderT r m a)+    deriving (Monad, MonadTrans, MonadIO)++instance Monad m => MonadReader r (WebReaderT r m) where+    ask = WebReaderT ask+    local f (WebReaderT cont) = WebReaderT (local f cont)++instance WebTrans (WebReaderT r) where+    liftWeb web = WebReaderT (lift web)+    liftWebFun f cont = WebReaderT $ ask >>= lift . f . runWebReaderT cont++instance Web m => Web (WebReaderT r m) where+    type WebRes (WebReaderT r m) = WebRes m+    webRec = liftWebRec (liftM id) webRec++runWebReaderT :: Monad m => WebReaderT r m a -> r -> m a+runWebReaderT (WebReaderT readerT) = runReaderT readerT
− src/Factis/Haskoon/WebRqAccessM.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Factis.Haskoon.WebRqAccessM-    (RqData(..), RqAccess(..), RqAccessM(..), runRqAccessM)-where--------------------------------------------- STDLIB------------------------------------------import Control.Monad (MonadPlus, liftM)-import Control.Monad.Reader (MonadReader(ask,local),ReaderT(runReaderT),asks)--------------------------------------------- SITE-PACKAGES------------------------------------------import Safe (atMay)--------------------------------------------- LOCAL------------------------------------------import Factis.Haskoon.Web (RqAccess(..))--data RqData = RqData { rqd_method :: String-                     , rqd_params :: [(String,String)]-                     , rqd_headers :: [(String,String)]-                     , rqd_repls :: [String]-                     , rqd_cookies :: [(String, String)]-                     }--type RqRead a = ReaderT RqData (Either String) a--newtype RqAccessM a = RqAccessM (RqRead a) deriving (Monad, MonadPlus)---instance RqAccess RqAccessM where-    param n = RqAccessM (readFromPairs rqd_params n "Parameter")-    repl i = RqAccessM (readFromRqData rqd_repls (flip atMay i) desc)-        where desc = "Replacement "++show i-    cookie n = RqAccessM (readFromPairs rqd_cookies n "Cookie")-    header n = RqAccessM (readFromPairs rqd_headers n "Header")-    checkMethod pred = RqAccessM $-                       do meth <- asks rqd_method-                          if pred meth-                             then return meth-                             else fail $ "Invalid request method `"++meth++"'."--readFromPairs :: (Eq a,Show a) => (RqData -> [(a,b)]) -> a -> String -> RqRead b-readFromPairs rqd_pairs key name = readFromRqData rqd_pairs findIn desc-    where findIn = lookup key-          desc = name ++ " `"++show key++"'"--readFromRqData :: (RqData -> a) -> (a -> Maybe b) -> String -> RqRead b-readFromRqData rqd_value findIn desc =-    do value <- asks rqd_value-       case findIn value of-         Nothing -> fail $ desc ++ " not found."-         Just v -> return v--runRqAccessM (RqAccessM r) d = runReaderT r d
src/Factis/Haskoon/WebSitemap.hs view
@@ -10,8 +10,8 @@ ---------------------------------------- -- STDLIB -----------------------------------------import Control.Monad (MonadPlus(..), msum, guard)-import Control.Monad.Trans (MonadIO,MonadTrans,lift,liftIO)+import Control.Monad (MonadPlus(..), msum, guard, liftM)+import Control.Monad.Trans (MonadIO,MonadTrans,lift)  ---------------------------------------- -- SITE-PACKAGES@@ -23,8 +23,8 @@ ---------------------------------------- -- LOCAL -----------------------------------------import Factis.Haskoon.Web (Web(..),WebRes,WebIO-                          ,webPathInfo,webMethod,webLogNotice,webNotFound)+import Factis.Haskoon.Web (Web(..),WebIO,webLogNotice,webNotFound)+import Factis.Haskoon.WebTrans (WebTrans(..), liftWebRec)   type Sitemap m = [SitemapT m (WebRes m)]@@ -32,37 +32,19 @@ newtype SitemapT m a = SitemapT { unSitemapT :: MaybeT m a }     deriving (Monad, MonadIO, MonadTrans) -liftWeb :: Web m => m a -> SitemapT m a-liftWeb web = SitemapT (lift web)--liftMaybe :: Web m => m (Maybe a) -> SitemapT m a-liftMaybe web = SitemapT (MaybeT web)- instance Web m => Web (SitemapT m) where     type WebRes (SitemapT m) = WebRes m-    webDocumentRoot = liftWeb webDocumentRoot-    webContainerUri = liftWeb webContainerUri-    webRequestUri = liftWeb webRequestUri-    webPathInfo = liftWeb webPathInfo-    webMethod = liftWeb webMethod-    webGetBody = liftWeb webGetBody-    webGetParams = liftWeb webGetParams-    webGetHeaders = liftWeb webGetHeaders-    webGetCookies = liftWeb webGetCookies-    webSetStatus code mmsg = liftWeb (webSetStatus code mmsg)-    webSendBSL bsl = liftWeb (webSendBSL bsl)-    webSetHeader k m = liftWeb (webSetHeader k m)-    webFail msg = liftWeb (webFail msg)-    webSetCookie c = liftWeb (webSetCookie c)-    webUnsetCookie c = liftWeb (webUnsetCookie c)-    webGetRepls = liftWeb webGetRepls+    webRec = liftWebRec (liftM id) webRec+    webFail = liftWeb . webFail     webWithRepls rs cont = liftMaybe (webWithRepls rs (runSitemapT cont))-    webRunFromRq = liftWeb webRunFromRq-    webLog name prio msg = liftWeb (webLog name prio msg)-    webSendError code msg = liftWeb (webSendError code msg)-    webGetHeader n = liftWeb (webGetHeader n)-    webGetParam n = liftWeb (webGetParam n) +instance WebTrans SitemapT where+    liftWeb web = SitemapT (lift web)+    liftWebFun f cont = liftMaybe (f (runSitemapT cont))++liftMaybe :: Web m => m (Maybe a) -> SitemapT m a+liftMaybe web = SitemapT (MaybeT web)+ instance Web m => MonadPlus (SitemapT m) where     mzero = liftMaybe (return Nothing)     mplus (SitemapT (MaybeT runX)) (SitemapT (MaybeT runY)) =@@ -108,11 +90,11 @@   fromSitemapT :: Web m => SitemapT m (WebRes m) -> m (WebRes m) -> m (WebRes m)-fromSitemapT (SitemapT (MaybeT try)) catch =+fromSitemapT (SitemapT (MaybeT try)) onError =     do mresult <- try        case mresult of          Just result -> return result-         Nothing -> catch+         Nothing -> onError   runWithSitemap :: Web m => (m (WebRes m) -> a) -> Sitemap m -> a
+ src/Factis/Haskoon/WebTrans.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE Rank2Types #-}+module Factis.Haskoon.WebTrans (WebTrans(..), liftWebRec) where++----------------------------------------+-- STDLIB+----------------------------------------+import Control.Monad.Trans (MonadTrans)++----------------------------------------+-- LOCAL+----------------------------------------+import Factis.Haskoon.Web (Web(..), WebRec(..))++class MonadTrans t => WebTrans t where+    liftWeb :: Web m => m a -> t m a+    liftWebFun :: Web m => (forall a. m a -> m a) -> t m b -> t m b++liftWebRec :: (Web m, WebTrans t) => (m (WebRes m) -> m (WebRes (t m))) -> WebRec m -> WebRec (t m)+liftWebRec liftRes wr =+    WebRec+    { web_documentRoot = lift0 (web_documentRoot wr)+    , web_containerUri = lift0 (web_containerUri wr)+    , web_requestUri = lift0 (web_requestUri wr)+    , web_pathInfo = lift0 (web_pathInfo wr)+    , web_method = lift0 (web_method wr)+    , web_getBody = lift0 (web_getBody wr)+    , web_getParams = lift0 (web_getParams wr)+    , web_getHeaders = lift0 (web_getHeaders wr)+    , web_getCookies = lift0 (web_getCookies wr)+    , web_setStatus = lift2 (web_setStatus wr)+    , web_sendBSL = \x -> lift0 (liftRes $ web_sendBSL wr x)+    , web_setHeader = lift2 (web_setHeader wr)+    , web_setCookie = lift1 (web_setCookie wr)+    , web_unsetCookie = lift1 (web_unsetCookie wr)+    , web_log = lift3 (web_log wr)+    , web_getRepls = lift0 (web_getRepls wr)+    , web_withRepls = \rs cont -> liftWebFun (web_withRepls wr rs) cont+    , web_fail = lift1 (web_fail wr)+    }+    where+      lift0 = liftWeb+      lift1 f x = lift0 (f x)+      lift2 f x y = lift0 (f x y)+      lift3 f x y z = lift0 (f x y z)