Luke Plant avatar Luke Plant committed 95354f6

Added a bunch of documentation

Comments (0)

Files changed (6)

src/Ella/Framework.hs

 {-# OPTIONS_GHC -fglasgow-exts -XOverloadedStrings #-}
 module Ella.Framework (
                       -- * Dispatching
+                      -- $dispatching
                       dispatchCGI
                      , sendResponseCGI
                      , dispatchRequest
                      , DispatchOptions(..)
+                      -- * Defaults
                      , defaultDispatchOptions
                      , default404
                      , default500
 
 -- * Dispatching
 
+-- $dispatching
+--
+-- The main entry point for handling CGI requests is @dispatchCGI@
+-- . This creates a Request object according to the CGI protocol, and
+-- dispatches it to a list of views, return a 404 if no view matches.
+-- This process can be customised using @DispatchOptions@.  A set of
+-- defaults for this is provided, @defaultDispatchOptions@, which can
+-- be used as a starting point and customised as needed.
+--
+-- @dispatchCGI@ does not do any error handling.  Since the type of
+-- any error handling function will depend on the libraries being
+-- used, it is easier to wrap the call to @dispatchCGI@ in your own
+-- error handling.  For finer grained error handling, view decorator
+-- functions can be used.
+
+-- | Options for the dispatch process
 data DispatchOptions = DispatchOptions {
       notFoundHandler :: Request -> IO Response
     -- ^ function that will return a 404 page in the case of no view functions matching
 
 -- * Defaults
 
+-- | A basic 404 response that is used by @defaultDispatchOptions@
 default404 = buildResponse [
               setStatus 404,
               addContent "<h1>404 Not Found</h1>\n<p>Sorry, the page you requested could not be found.</p>"
              ] utf8HtmlResponse
 
+-- | A basic 500 response, not used internally.
 default500 content = buildResponse [ setStatus 500
                                    , addContent "<h1>500 Internal Server Error</h1>\n"
                                    , addContent $ utf8 content
                                    ] utf8HtmlResponse
 
+-- | Default options used for interpreting the request
 defaultRequestOptions = RequestOptions {
                           encoding = utf8Encoding
                         }
 
+-- | A set of DispatchOptions useful as a basis.
 defaultDispatchOptions = DispatchOptions {
                            notFoundHandler = const $ return $ default404
                          , requestOptions = defaultRequestOptions
                          }
 
--- Dispatching
-
 -- | Used by dispatchCGI, might be useful on its own, especially in testing
 --
 -- Effectively this reduces a list of view functions so that
 --
 -- > fixedString "thestring/"
 --
--- The result of the //-> operator needs to be passed a list of \'view
+-- The result of the //-> operator needs to be applied to a list of \'view
 -- decorator\' functions, (which may be an empty list) e.g. \'decs\'
 -- above.  These decorators take a View and return a View, or
 -- alternatively they take a View and a Request and return an IO

src/Ella/GenUtils.hs

 instance IsString ByteString where
     fromString = UTF8.fromString
 
+-- | Takes a String and returns UTF8 ByteString
+utf8 :: String -> ByteString
 utf8 = UTF8.fromString
 
 -- | Apply a list of transformation functions to an object
 apply fs init = foldl (flip ($)) init fs
 
 -- | Same as apply with arguments flipped
+with :: a -> [a -> a] -> a
 with = flip apply

src/Ella/Processors/General.hs

 module Ella.Processors.General
-    ( addSlashRedirectView
+    (
+     -- * Processors
+     -- $processors
+     addSlashRedirectView
     )
 
 where
 import Ella.Request
 import Ella.Response
 
--- ** View processors
-
+-- $processors
+--
+-- Processors are used for doing various tasks, usually not limited
+-- in usefulness to one particular view function.
+--
+-- * View processors
+--
 --  These take a view function and return a view function.
 --  Alternatively, take a view function and a request and return an IO
 --  (Maybe Response).  This allows them to do both request
 --  pre-processing and response post-processing.  They will be usually
 --  be used as \'decorators\' when defining routes.
-
--- ** View functions
-
+--
+-- * View functions
+--
 --  These are straightforward view functions which happen to work as a
 --  kind of pre-handler.  They are installed using routes, usually
 --  before all the others.  These usually do redirects, for example
---  addSlashRedirectView
-
--- ** Response processors
-
+--  @addSlashRedirectView@
+--
+-- * Response processors
+--
 --  These take a response and the original request object, and return
 --  a possibly modified response.  This can be useful for
 --  post-processing, or adding headers etc.

src/Ella/Request.hs

 module Ella.Request (
-                    -- * Encodings
-                    Encoding(..)
-                   , utf8Encoding
                     -- * Requests
-                   , Request
+                     Request
                    , RequestOptions(..)
                     -- ** Components of Request
                    , requestMethod
                    -- * Escaping
                    , escapePath
                    , escapePathWithEnc
+                    -- * Encodings
+                   , Encoding(..)
+                   , utf8Encoding
                    )
 
 where
 
 -- Encodings
 
+-- | Used to store conversion functions need to interpret CGI requests
 data Encoding = Encoding {
       name :: String
     -- ^ descriptive name of the encoding
 instance Show Encoding where
     show x = "Encoding " ++ name x
 
--- Defaults
+-- * Defaults
 
+-- | An @Encoding@ for UTF8
+utf8Encoding :: Encoding
 utf8Encoding = Encoding {
                  name = "UTF8"
                , decoder = UTF8.toString
                , encoder = UTF8.fromString
                }
 
-
 -- | Options that affect the way that HTTP requests are handled
 data RequestOptions = RequestOptions {
       encoding :: Encoding -- ^ Handles request encoding translation
     } deriving (Eq, Show)
 
+-- | Represents a CGI request.  This contains the fundamental data
+-- that is passed around the CGI application.  Accessor functions
+-- are provided to extract all the useful information.
 data Request = Request {
       environment :: Map.Map String String
     , requestBody :: ByteString
 
 -- | Returns the path info of the request, with any leading forward slash removed,
 -- and percent encoded chars interpreted according to the encoding.
+pathInfo :: Request -> String
 pathInfo request = let pi = Map.lookup "PATH_INFO" $ environment request
                        -- Normalise to having no leading slash
                        adjusted = case pi of
 -- contain uninterpreted byte sequences instead of Unicode chars.  We
 -- re-pack as bytes (BS.pack discards anything > \255), and then
 -- re-interpret.
+repack :: String -> Encoding -> String
 repack str encoding = let bytes = BS.pack str
                       in (decoder encoding) bytes
 

src/Ella/Response.hs

-module Ella.Response ( Response
+module Ella.Response (
+                      -- * Response object
+                      Response
                     , content
                     , headers
+                    , HeaderName(HeaderName)
+                    -- * Building Response objects
+                    , buildResponse
                     , addContent
+                    , setStatus
+                    , setHeader
+                    -- * Starting points for Response objects
                     , textResponse
                     , utf8TextResponse
                     , htmlResponse
                     , utf8HtmlResponse
                     , emptyResponse
                     , redirectResponse
+                    -- * Using Response objects
                     , formatResponse
-                    , setStatus
-                    , setHeader
-                    , buildResponse
-                    , HeaderName(HeaderName)
                     ) where
 
 import Data.ByteString.Lazy.Char8 (ByteString)
 import Network.CGI (ContentType(ContentType), showContentType)
 import Ella.GenUtils (apply)
 
+-- | Represents an HTTP response
 data Response = Response {
-      content :: ByteString
-    , headers :: Headers
+      content :: ByteString -- ^ The body of the response
+    , headers :: Headers    -- ^ The HTTP headers of the response
     , status :: Int
     } deriving (Show, Eq)
 
 -- * Creating responses
 --
 
+-- | A basic, empty 200 OK response
+emptyResponse :: Response
 emptyResponse = Response { content = BS.empty
                          , headers = []
                          , status = 200
                          }
 
+-- | Add a string to a response
 addContent :: ByteString -> Response -> Response
 addContent c resp = resp { content =  BS.append (content resp) c }
 
+-- | Set the HTTP status code of a response
 setStatus :: Int -> Response -> Response
 setStatus s resp = resp { status = s }
 
+-- | Set an HTTP header.  Previous values (if present) will be overwritten
 setHeader :: String -> String -> Response -> Response
 setHeader h val resp = let headername = HeaderName h
                            removed = filter ((/= headername) . fst) (headers resp)
 textContent charset = "text/plain; charset=" ++ charset
 htmlContent charset = "text/html; charset=" ++ charset
 
+-- | An empty text/plain response of a given charset
+textResponse :: String -> Response
 textResponse charset = emptyResponse {
                          headers = [(contentTypeName, textContent charset)]
                        }
 
+-- | An empty text/html response of a given charset
+htmlResponse :: String -> Response
 htmlResponse charset = emptyResponse {
                          headers = [(contentTypeName, htmlContent charset)]
                        }
 
+-- | An empty UTF8 text/plain response.  The user is responsible
+-- for ensuing that that content added to this response is actually
+-- UTF8 ByteStrings.
+utf8TextResponse :: Response
 utf8TextResponse = textResponse "UTF-8"
 
--- | Create an empty response for sending HTML, UTF-8 encoding
+-- | An empty UTF8 text/html response.  The user is responsible
+-- for ensuing that that content added to this response is actually
+-- UTF8 ByteStrings.
+utf8HtmlResponse :: Response
 utf8HtmlResponse = htmlResponse "UTF-8"
 
 -- | Build a Response from a list of Response transformation functions
--- and an initial Response
+-- and an initial Response.
+--
+-- This is a convenient way of creating responses:
+--
+-- > resp = buildResponse [ setHeader "Location" foo
+-- >                      , setStatus 302
+-- >                      ] utf8HtmlResponse
 buildResponse :: [Response -> Response] -> Response -> Response
 buildResponse = apply
 
     let statusHeader = (HeaderName "Status", show $ status resp)
     in headers resp ++ [statusHeader]
 
--- | Convert a Response into the format needed for HTTP
+-- | Convert a Response into the format needed for HTTP.
+--
 -- Copied from Network.CGI.Protocol, thank you Bjorn Bringert :-)
 formatResponse :: Response -> ByteString
 formatResponse resp =
 
 
 -- | Create an HTTP 302 redirect
+redirectResponse :: String -> Response
 redirectResponse location =
     buildResponse [ setStatus 302
                   , setHeader "Location" location

src/Ella/Utils.hs

 
 where
 
-import Text.XHtml (renderHtml)
-import Ella.Response (addContent)
+import Text.XHtml (renderHtml, HTML)
+import Ella.Response (addContent, Response)
 import Ella.GenUtils (utf8)
 
 -- Utility functions
+
+-- | Adds HTML to a response
+addHtml :: (HTML html) => html -> Response -> Response
 addHtml html resp = addContent (utf8 $ renderHtml html) resp
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.