    {-# LANGUAGE CPP #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Network.CGI
    -- Copyright   :  (c) The University of Glasgow 2001
    --                (c) Bjorn Bringert 2004-2006
    --                (c) Ian Lynagh 2005
    --                (c) Jeremy Shaw 2005
    -- License     :  BSD-style
    --
    -- Maintainer  :  John Chee <cheecheeo@gmail.com>
    -- Stability   :  experimental
    -- Portability :  non-portable (uses Control.Monad.State)
    --
    -- Simple Library for writing CGI programs.
    -- See <https://web.archive.org/web/20100109233524/http://hoohoo.ncsa.illinois.edu/cgi/interface.html> for the
    -- CGI specification.
    --
    -- This version of the library is for systems with version 2.0 or greater
    -- of the network package. This includes GHC 6.6 and later. For older
    -- systems, see <http://www.cs.chalmers.se/~bringert/darcs/cgi-compat/doc/>
    --
    -- Based on the original Haskell binding for CGI:
    --
    -- Original Version by Erik Meijer <mailto:erik@cs.ruu.nl>.
    -- Further hacked on by Sven Panne <mailto:sven.panne@aedion.de>.
    -- Further hacking by Andy Gill <mailto:andy@galconn.com>.
    -- A new, hopefully more flexible, interface
    -- and support for file uploads by Bjorn Bringert <mailto:bjorn@bringert.net>.
    --
    -- Here is a simple example, including error handling (not that there is
    -- much that can go wrong with Hello World):
    --
    -- > import Network.CGI
    -- >
    -- > cgiMain :: CGI CGIResult
    -- > cgiMain = output "Hello World!"
    -- >
    -- > main :: IO ()
    -- > main = runCGI (handleErrors cgiMain)
    --
    --
    -----------------------------------------------------------------------------

    module Network.CGI (
      -- * CGI monad
        MonadCGI, CGIT, CGIResult, CGI
      , MonadIO, liftIO
      , runCGI
      -- * Error handling
      , throwCGI, catchCGI, tryCGI, handleExceptionCGI
      , handleErrors
      -- * Logging
      , logCGI
      -- * Output
      , output, outputFPS, outputNothing, redirect
      , setHeader, setStatus
      -- * Error pages
      , outputError, outputException
      , outputNotFound, outputMethodNotAllowed, outputInternalServerError
      -- * Input
      , getInput, getInputFPS, readInput
      , getBody, getBodyFPS
      , getInputs, getInputsFPS, getInputNames
      , getMultiInput, getMultiInputFPS
      , getInputFilename, getInputContentType
      -- * Environment
      , getVar, getVarWithDefault, getVars
      -- * Request information
      , serverName, serverPort
      , requestMethod, pathInfo
      , pathTranslated, scriptName
      , queryString
      , remoteHost, remoteAddr
      , authType, remoteUser
      , requestContentType, requestContentLength
      , requestHeader
      -- * Program and request URI
      , progURI, queryURI, requestURI
      -- * Content negotiation
      , Acceptable, Accept
      , Charset(..), ContentEncoding(..), Language(..)
      , requestAccept, requestAcceptCharset, requestAcceptEncoding, requestAcceptLanguage
      , negotiate
      -- * Content type
      , ContentType(..), showContentType, parseContentType
      -- * Cookies
      , Cookie(..), newCookie
      , getCookie, readCookie
      , setCookie, deleteCookie
      -- * URL encoding
      , formEncode, urlEncode, formDecode, urlDecode
      ) where

    import Control.Exception (Exception(..), SomeException, ErrorCall(..))
    import Control.Monad.Catch (MonadCatch(..), handle)
    import Control.Monad.Trans (MonadIO, liftIO)
    import Data.Char (toUpper)
    import Data.List (intercalate, sort, group)
    import Data.Maybe (fromMaybe, isJust)
    import qualified Data.Map as Map
    import Network.Multipart
    import Network.Multipart.Header
    import Network.URI (URI(..), URIAuth(..), nullURI, parseRelativeReference,
                        escapeURIString, isUnescapedInURI)
    import System.IO (stdin, stdout)

    import qualified Data.ByteString.Lazy.Char8 as BS
    import Data.ByteString.Lazy.Char8 (ByteString)

    import Network.CGI.Cookie (Cookie(..), showCookie, newCookie, findCookie)
    import qualified Network.CGI.Cookie as Cookie (deleteCookie)
    import Network.CGI.Accept
    import Network.CGI.Monad
    import Network.CGI.Protocol

    import Text.XHtml (Html, renderHtml, header, (<<), thetitle, (+++),
                       body, h1, paragraph, hr, address)

    #if MIN_VERSION_xhtml(3000,3,0)
    import Data.ByteString.Builder (toLazyByteString)
    import qualified Data.Text.Lazy as LText
    import qualified Data.Text.Lazy.Encoding as LText
    import Text.XHtml (Builder)

    -- Taken from Text.XHtml.Internal
    builderToString :: Builder -> String
    builderToString = LText.unpack . LText.decodeUtf8 . toLazyByteString
    #endif

    -- | Run a CGI action. Typically called by the main function.
    --   Reads input from stdin and writes to stdout. Gets
    --   CGI environment variables from the program environment.
    runCGI :: MonadIO m => CGIT m CGIResult -> m ()
    runCGI :: forall (m :: * -> *). MonadIO m => CGIT m CGIResult -> m ()
    runCGI CGIT m CGIResult
    f = do env <- m [(String, String)]
    forall (m :: * -> *). MonadIO m => m [(String, String)]
    getCGIVars
                  hRunCGI env stdin stdout (runCGIT f)

    --
    -- * Output \/ redirect
    --

    -- | Output a 'String'. The output is assumed to be text\/html, encoded using
    --   ISO-8859-1. To change this, set the Content-type header using
    --   'setHeader'.
    output :: MonadCGI m =>
              String        -- ^ The string to output.
           -> m CGIResult
    output :: forall (m :: * -> *). MonadCGI m => String -> m CGIResult
    output = CGIResult -> m CGIResult
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CGIResult -> m CGIResult)
    -> (String -> CGIResult) -> String -> m CGIResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> CGIResult
    CGIOutput (ByteString -> CGIResult)
    -> (String -> ByteString) -> String -> CGIResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ByteString
    BS.pack

    -- | Output a 'ByteString'. The output is assumed to be text\/html,
    --   encoded using ISO-8859-1. To change this, set the
    --   Content-type header using 'setHeader'.
    outputFPS :: MonadCGI m =>
                 ByteString        -- ^ The string to output.
              -> m CGIResult
    outputFPS :: forall (m :: * -> *). MonadCGI m => ByteString -> m CGIResult
    outputFPS = CGIResult -> m CGIResult
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (CGIResult -> m CGIResult)
    -> (ByteString -> CGIResult) -> ByteString -> m CGIResult
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> CGIResult
    CGIOutput

    -- | Do not output anything (except headers).
    outputNothing :: MonadCGI m => m CGIResult
    outputNothing :: forall (m :: * -> *). MonadCGI m => m CGIResult
    outputNothing = CGIResult -> m CGIResult
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CGIResult
    CGINothing

    -- | Redirect to some location.
    redirect :: MonadCGI m =>
                String        -- ^ A URL to redirect to.
             -> m CGIResult
    redirect :: forall (m :: * -> *). MonadCGI m => String -> m CGIResult
    redirect String
    url = do String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Location" String
    url
                      m CGIResult
    forall (m :: * -> *). MonadCGI m => m CGIResult
    outputNothing

    --
    -- * Error handling
    --

    -- | Catches any exception thrown by the given CGI action,
    --   returns an error page with a 500 Internal Server Error,
    --   showing the exception information, and logs the error.
    --
    --   Typical usage:
    --
    -- > cgiMain :: CGI CGIResult
    -- > cgiMain = ...
    -- >
    -- > main :: IO ()
    -- > main = runCGI (handleErrors cgiMain)
    handleErrors :: (MonadCGI m, MonadCatch m, MonadIO m) => m CGIResult -> m CGIResult
    handleErrors :: forall (m :: * -> *).
    (MonadCGI m, MonadCatch m, MonadIO m) =>
    m CGIResult -> m CGIResult
    handleErrors = (SomeException -> m CGIResult) -> m CGIResult -> m CGIResult
    forall (m :: * -> *) e a.
    (HasCallStack, MonadCatch m, Exception e) =>
    (e -> m a) -> m a -> m a
    handle SomeException -> m CGIResult
    forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    SomeException -> m CGIResult
    outputException

    --
    -- * Error output
    --

    -- | Output a 500 Internal Server Error with information from
    --   an 'Exception'.
    outputException :: (MonadCGI m,MonadIO m) => SomeException -> m CGIResult
    outputException :: forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    SomeException -> m CGIResult
    outputException SomeException
    e = [String] -> m CGIResult
    forall (m :: * -> *).
    (MonadIO m, MonadCGI m) =>
    [String] -> m CGIResult
    outputInternalServerError [String]
    es
        where es :: [String]
    es = case SomeException -> Maybe ErrorCall
    forall e. Exception e => SomeException -> Maybe e
    fromException SomeException
    e of
                     Just (ErrorCall String
    msg) -> [String
    msg]
                     Maybe ErrorCall
    _ -> [SomeException -> String
    forall a. Show a => a -> String
    show SomeException
    e]

    -- | Output an error page to the user, with the given
    --   HTTP status code in the response. Also logs the error information
    --   using 'logCGI'.
    outputError :: (MonadCGI m, MonadIO m) =>
                   Int      -- ^ HTTP Status code
                -> String   -- ^ Status message
                -> [String] -- ^ Error information
                -> m CGIResult
    outputError :: forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    Int -> String -> [String] -> m CGIResult
    outputError Int
    c String
    m [String]
    es =
          do String -> m ()
    forall (m :: * -> *). MonadIO m => String -> m ()
    logCGI (String -> m ()) -> String -> m ()
    forall a b. (a -> b) -> a -> b
    $ (Int, String, [String]) -> String
    forall a. Show a => a -> String
    show (Int
    c,String
    m,[String]
    es)
             Int -> String -> m ()
    forall (m :: * -> *). MonadCGI m => Int -> String -> m ()
    setStatus Int
    c String
    m
             let textType :: ContentType
    textType = String -> String -> [(String, String)] -> ContentType
    ContentType String
    "text" String
    "plain" [(String
    "charset",String
    "ISO-8859-1")]
                 htmlType :: ContentType
    htmlType = String -> String -> [(String, String)] -> ContentType
    ContentType String
    "text" String
    "html"  [(String
    "charset",String
    "ISO-8859-1")]
             cts <- (Maybe (Accept ContentType) -> [ContentType])
    -> m (Maybe (Accept ContentType)) -> m [ContentType]
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([ContentType] -> Maybe (Accept ContentType) -> [ContentType]
    forall a. Acceptable a => [a] -> Maybe (Accept a) -> [a]
    negotiate [ContentType
    htmlType,ContentType
    textType]) m (Maybe (Accept ContentType))
    forall (m :: * -> *). MonadCGI m => m (Maybe (Accept ContentType))
    requestAccept
             case cts of
               ContentType
    ct:[ContentType]
    _ | ContentType
    ct ContentType -> ContentType -> Bool
    forall a. Eq a => a -> a -> Bool
    == ContentType
    textType ->
                    do String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Content-type" (ContentType -> String
    showContentType ContentType
    textType)
                       text <- Int -> String -> [String] -> m String
    forall (m :: * -> *).
    MonadCGI m =>
    Int -> String -> [String] -> m String
    errorText Int
    c String
    m [String]
    es
                       output text
               [ContentType]
    _ -> do String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Content-type" (ContentType -> String
    showContentType ContentType
    htmlType)
                       page <- Int -> String -> [String] -> m Html
    forall (m :: * -> *).
    MonadCGI m =>
    Int -> String -> [String] -> m Html
    errorPage Int
    c String
    m [String]
    es
    #if MIN_VERSION_xhtml(3000,3,0)
                       output $ builderToString $ renderHtml page
    #else
                       output $ renderHtml page
    #endif

    -- | Create an HTML error page.
    errorPage :: MonadCGI m =>
                 Int      -- ^ Status code
              -> String   -- ^ Status message
              -> [String] -- ^ Error information
              -> m Html
    errorPage :: forall (m :: * -> *).
    MonadCGI m =>
    Int -> String -> [String] -> m Html
    errorPage Int
    c String
    m [String]
    es =
        do server <- String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "SERVER_SOFTWARE"
           host   <- getVar "SERVER_NAME"
           port   <- getVar "SERVER_PORT"
           let tit = Int -> String
    forall a. Show a => a -> String
    show Int
    c String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    m
               sig = String
    "Haskell CGI"
                     String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " on " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    "" Maybe String
    server
                     String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " at " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    "" Maybe String
    host String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String -> (String -> String) -> Maybe String -> String
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe String
    "" (String
    ", port "String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++) Maybe String
    port
           return $ header << thetitle << tit
                      +++ body << (h1 << tit +++ map (paragraph <<) es
                                   +++ hr +++ address << sig)

    errorText :: MonadCGI m =>
                 Int      -- ^ Status code
              -> String   -- ^ Status message
              -> [String] -- ^ Error information
              -> m String
    errorText :: forall (m :: * -> *).
    MonadCGI m =>
    Int -> String -> [String] -> m String
    errorText Int
    c String
    m [String]
    es = String -> m String
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> m String) -> String -> m String
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    unlines ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ (Int -> String
    forall a. Show a => a -> String
    show Int
    c String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    m) String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [String]
    es

    --
    -- * Specific HTTP errors
    --

    -- | Use 'outputError' to output and log a 404 Not Found error.
    outputNotFound :: (MonadIO m, MonadCGI m) =>
                     String -- ^ The name of the requested resource.
                  -> m CGIResult
    outputNotFound :: forall (m :: * -> *).
    (MonadIO m, MonadCGI m) =>
    String -> m CGIResult
    outputNotFound String
    r =
        Int -> String -> [String] -> m CGIResult
    forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    Int -> String -> [String] -> m CGIResult
    outputError Int
    404 String
    "Not Found" [String
    "The requested resource was not found: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    r]

    -- | Use 'outputError' to output and log a 405 Method Not Allowed error.
    outputMethodNotAllowed :: (MonadIO m, MonadCGI m) =>
                              [String] -- ^ The allowed methods.
                           -> m CGIResult
    outputMethodNotAllowed :: forall (m :: * -> *).
    (MonadIO m, MonadCGI m) =>
    [String] -> m CGIResult
    outputMethodNotAllowed [String]
    ms =
        do let allow :: String
    allow = String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    ", " [String]
    ms
           String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Allow" String
    allow
           Int -> String -> [String] -> m CGIResult
    forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    Int -> String -> [String] -> m CGIResult
    outputError Int
    405 String
    "Method Not Allowed" [String
    "Allowed methods : " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    allow]

    -- | Use 'outputError' to output and log a 500 Internal Server Error.
    outputInternalServerError :: (MonadIO m, MonadCGI m) =>
                                 [String] -- ^ Error information.
                              -> m CGIResult
    outputInternalServerError :: forall (m :: * -> *).
    (MonadIO m, MonadCGI m) =>
    [String] -> m CGIResult
    outputInternalServerError = Int -> String -> [String] -> m CGIResult
    forall (m :: * -> *).
    (MonadCGI m, MonadIO m) =>
    Int -> String -> [String] -> m CGIResult
    outputError Int
    500 String
    "Internal Server Error"

    --
    -- * Environment variables
    --

    -- | Get the value of a CGI environment variable. Example:
    --
    -- > remoteAddr <- getVar "REMOTE_ADDR"
    getVar :: MonadCGI m =>
              String             -- ^ The name of the variable.
           -> m (Maybe String)
    getVar :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    name = String -> Map String String -> Maybe String
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup String
    name (Map String String -> Maybe String)
    -> m (Map String String) -> m (Maybe String)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (CGIRequest -> Map String String) -> m (Map String String)
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> Map String String
    cgiVars

    getVarWithDefault :: MonadCGI m =>
                         String -- ^ The name of the variable.
                      -> String -- ^ Default value
                      -> m String
    getVarWithDefault :: forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    name String
    def = String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    def (Maybe String -> String) -> m (Maybe String) -> m String
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    name

    -- | Get all CGI environment variables and their values.
    getVars :: MonadCGI m =>
               m [(String,String)]
    getVars :: forall (m :: * -> *). MonadCGI m => m [(String, String)]
    getVars = Map String String -> [(String, String)]
    forall k a. Map k a -> [(k, a)]
    Map.toList (Map String String -> [(String, String)])
    -> m (Map String String) -> m [(String, String)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (CGIRequest -> Map String String) -> m (Map String String)
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> Map String String
    cgiVars

    --
    -- * Request information
    --

    -- | The server\'s hostname, DNS alias, or IP address as it would
    --   appear in self-referencing URLs.
    serverName :: MonadCGI m => m String
    serverName :: forall (m :: * -> *). MonadCGI m => m String
    serverName = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "SERVER_NAME" String
    ""

    -- | The port number to which the request was sent.
    serverPort :: MonadCGI m => m Int
    serverPort :: forall (m :: * -> *). MonadCGI m => m Int
    serverPort = (Maybe String -> Int) -> m (Maybe String) -> m Int
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe Int
    80 (Maybe Int -> Int)
    -> (Maybe String -> Maybe Int) -> Maybe String -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Maybe String -> (String -> Maybe Int) -> Maybe Int
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> Maybe Int
    forall a. Read a => String -> Maybe a
    maybeRead)) (String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "SERVER_PORT")

    -- |  The method with which the request was made.
    --    For HTTP, this is \"GET\", \"HEAD\", \"POST\", etc.
    requestMethod :: MonadCGI m => m String
    requestMethod :: forall (m :: * -> *). MonadCGI m => m String
    requestMethod = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "REQUEST_METHOD" String
    "GET"

    -- | The extra path information, as given by the client.
    --   This is any part of the request path that follows the
    --   CGI program path.
    --   If the string returned by this function is not empty,
    --   it is guaranteed to start with a @\'\/\'@.
    --
    -- Note that this function returns an unencoded string.
    -- Make sure to percent-encode any characters
    -- that are not allowed in URI paths before using the result of
    -- this function to construct a URI.
    -- See 'progURI', 'queryURI' and 'requestURI' for a higher-level
    -- interface.
    pathInfo :: MonadCGI m => m String
    pathInfo :: forall (m :: * -> *). MonadCGI m => m String
    pathInfo = String -> String
    slash (String -> String) -> m String -> m String
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "PATH_INFO" String
    ""
      where slash :: String -> String
    slash String
    s = if Bool -> Bool
    not (String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    s) Bool -> Bool -> Bool
    && String -> Char
    forall a. HasCallStack => [a] -> a
    head String
    s Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    '/' then Char
    '/'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String
    s else String
    s

    -- | The path returned by 'pathInfo', but with virtual-to-physical
    --   mapping applied to it.
    pathTranslated :: MonadCGI m => m String
    pathTranslated :: forall (m :: * -> *). MonadCGI m => m String
    pathTranslated = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "PATH_TRANSLATED" String
    ""

    -- | A virtual path to the script being executed,
    -- used for self-referencing URIs.
    --
    -- Note that this function returns an unencoded string.
    -- Make sure to percent-encode any characters
    -- that are not allowed in URI paths before using the result of
    -- this function to construct a URI.
    -- See 'progURI', 'queryURI' and 'requestURI' for a higher-level
    -- interface.
    scriptName :: MonadCGI m => m String
    scriptName :: forall (m :: * -> *). MonadCGI m => m String
    scriptName = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "SCRIPT_NAME" String
    ""

    -- | The information which follows the ? in the URL which referenced
    --   this program. This is the percent-encoded query information.
    --   For most normal uses, 'getInput' and friends are probably
    --   more convenient.
    queryString :: MonadCGI m => m String
    queryString :: forall (m :: * -> *). MonadCGI m => m String
    queryString = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "QUERY_STRING" String
    ""

    -- | The hostname making the request. If the server does not have
    --   this information, Nothing is returned. See also 'remoteAddr'.
    remoteHost :: MonadCGI m => m (Maybe String)
    remoteHost :: forall (m :: * -> *). MonadCGI m => m (Maybe String)
    remoteHost = String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "REMOTE_HOST"

    -- | The IP address of the remote host making the request.
    remoteAddr :: MonadCGI m => m String
    remoteAddr :: forall (m :: * -> *). MonadCGI m => m String
    remoteAddr = String -> String -> m String
    forall (m :: * -> *). MonadCGI m => String -> String -> m String
    getVarWithDefault String
    "REMOTE_ADDR" String
    ""

    -- | If the server supports user authentication, and the script is
    -- protected, this is the protocol-specific authentication method
    -- used to validate the user.
    authType :: MonadCGI m => m (Maybe String)
    authType :: forall (m :: * -> *). MonadCGI m => m (Maybe String)
    authType = String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "AUTH_TYPE"

    -- | If the server supports user authentication, and the script is
    --   protected, this is the username they have authenticated as.
    remoteUser :: MonadCGI m => m (Maybe String)
    remoteUser :: forall (m :: * -> *). MonadCGI m => m (Maybe String)
    remoteUser = String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "REMOTE_USER"

    -- | For queries which have attached information, such as
    --   HTTP POST and PUT, this is the content type of the data.
    --   You can use 'parseContentType' to get a structured
    --   representation of the the content-type value.
    requestContentType :: MonadCGI m => m (Maybe String)
    requestContentType :: forall (m :: * -> *). MonadCGI m => m (Maybe String)
    requestContentType = String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "CONTENT_TYPE"

    -- | For queries which have attached information, such as
    --   HTTP POST and PUT, this is the length of the content
    --   given by the client.
    requestContentLength :: MonadCGI m => m (Maybe Int)
    requestContentLength :: forall (m :: * -> *). MonadCGI m => m (Maybe Int)
    requestContentLength = (Maybe String -> (String -> Maybe Int) -> Maybe Int
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> Maybe Int
    forall a. Read a => String -> Maybe a
    maybeRead) (Maybe String -> Maybe Int) -> m (Maybe String) -> m (Maybe Int)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "CONTENT_LENGTH"

    -- | Gets the value of the request header with the given name.
    --   The header name is case-insensitive.
    --   Example:
    --
    -- > requestHeader "User-Agent"
    requestHeader :: MonadCGI m => String -> m (Maybe String)
    requestHeader :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    requestHeader String
    name = String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    var
      where var :: String
    var = String
    "HTTP_" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toUpper (Char -> Char -> String -> String
    forall a. Eq a => a -> a -> [a] -> [a]
    replace Char
    '-' Char
    '_' String
    name)

    --
    -- * Content negotiation
    --

    requestHeaderValue :: (MonadCGI m, HeaderValue a) => String -> m (Maybe a)
    requestHeaderValue :: forall (m :: * -> *) a.
    (MonadCGI m, HeaderValue a) =>
    String -> m (Maybe a)
    requestHeaderValue String
    h = (Maybe String -> (String -> Maybe a) -> Maybe a
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Parser a -> String -> String -> Maybe a
    forall (m :: * -> *) a.
    MonadFail m =>
    Parser a -> String -> String -> m a
    parseM Parser a
    forall a. HeaderValue a => Parser a
    parseHeaderValue String
    h) (Maybe String -> Maybe a) -> m (Maybe String) -> m (Maybe a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    requestHeader String
    h

    requestAccept :: MonadCGI m => m (Maybe (Accept ContentType))
    requestAccept :: forall (m :: * -> *). MonadCGI m => m (Maybe (Accept ContentType))
    requestAccept = String -> m (Maybe (Accept ContentType))
    forall (m :: * -> *) a.
    (MonadCGI m, HeaderValue a) =>
    String -> m (Maybe a)
    requestHeaderValue String
    "Accept"

    requestAcceptCharset :: MonadCGI m => m (Maybe (Accept Charset))
    requestAcceptCharset :: forall (m :: * -> *). MonadCGI m => m (Maybe (Accept Charset))
    requestAcceptCharset = String -> m (Maybe (Accept Charset))
    forall (m :: * -> *) a.
    (MonadCGI m, HeaderValue a) =>
    String -> m (Maybe a)
    requestHeaderValue String
    "Accept-Charset"

    requestAcceptEncoding :: MonadCGI m => m (Maybe (Accept ContentEncoding))
    requestAcceptEncoding :: forall (m :: * -> *).
    MonadCGI m =>
    m (Maybe (Accept ContentEncoding))
    requestAcceptEncoding = String -> m (Maybe (Accept ContentEncoding))
    forall (m :: * -> *) a.
    (MonadCGI m, HeaderValue a) =>
    String -> m (Maybe a)
    requestHeaderValue String
    "Accept-Encoding"

    requestAcceptLanguage :: MonadCGI m => m (Maybe (Accept Language))
    requestAcceptLanguage :: forall (m :: * -> *). MonadCGI m => m (Maybe (Accept Language))
    requestAcceptLanguage = String -> m (Maybe (Accept Language))
    forall (m :: * -> *) a.
    (MonadCGI m, HeaderValue a) =>
    String -> m (Maybe a)
    requestHeaderValue String
    "Accept-Language"

    --
    -- * Program and request URI
    --

    -- | Attempts to reconstruct the absolute URI of this program.
    --   This does not include
    --   any extra path information or query parameters. See
    --   'queryURI' for that.
    --   If the server is rewriting request URIs, this URI can
    --   be different from the one requested by the client.
    --   See also 'requestURI'.
    --
    -- Characters in the components of the returned URI are escaped
    -- when needed, as required by "Network.URI".
    progURI :: MonadCGI m => m URI
    progURI :: forall (m :: * -> *). MonadCGI m => m URI
    progURI =
        do -- Use HTTP_HOST if available, otherwise SERVER_NAME
           h <- String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    requestHeader String
    "Host" m (Maybe String) -> (Maybe String -> m String) -> m String
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= m String -> (String -> m String) -> Maybe String -> m String
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe m String
    forall (m :: * -> *). MonadCGI m => m String
    serverName String -> m String
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
           p <- serverPort
           name <- scriptName
           https <- fmap isJust (getVar "HTTPS")
           -- SERVER_PORT might not be the port that the client used
           -- if the server listens on multiple ports, so we give priority
           -- to the port in HTTP_HOST.
           -- HTTP_HOST should include the port according to RFC2616 sec 14.23
           -- Some servers (e.g. lighttpd) also seem to include the port in
           -- SERVER_NAME.
           -- We include the port if it is in HTTP_HOST or SERVER_NAME, or if
           -- it is a non-standard port.
           let (host,port) = case break (==':') h of
                               (String
    _,String
    "")  -> (String
    h, if (Bool -> Bool
    not Bool
    https Bool -> Bool -> Bool
    && Int
    p Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    80)
                                                Bool -> Bool -> Bool
    || (Bool
    https Bool -> Bool -> Bool
    && Int
    p Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    443)
                                               then String
    "" else Char
    ':'Char -> String -> String
    forall a. a -> [a] -> [a]
    :Int -> String
    forall a. Show a => a -> String
    show Int
    p)
                               (String
    h',String
    p') -> (String
    h',String
    p')
           let auth = URIAuth { uriUserInfo :: String
    uriUserInfo = String
    "",
                                uriRegName :: String
    uriRegName = String
    host,
                                uriPort :: String
    uriPort = String
    port }
           return $ nullURI { uriScheme = if https then "https:" else "http:",
                              uriAuthority = Just auth,
                              uriPath = escapePath name }

    -- | Like 'progURI', but the returned 'URI' also includes
    --   any extra path information, and any query parameters.
    --   If the server is rewriting request URIs, this URI can
    --   be different from the one requested by the client.
    --   See also 'requestURI'.
    --
    -- Characters in the components of the returned URI are escaped
    -- when needed, as required by "Network.URI".
    queryURI :: MonadCGI m => m URI
    queryURI :: forall (m :: * -> *). MonadCGI m => m URI
    queryURI =
        do uri  <- m URI
    forall (m :: * -> *). MonadCGI m => m URI
    progURI
           path <- pathInfo
           qs   <- fmap (\String
    q -> if String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    q then String
    q else Char
    '?'Char -> String -> String
    forall a. a -> [a] -> [a]
    :String
    q) queryString
           return $ uri { uriPath = uriPath uri ++ escapePath path,
                          uriQuery = qs }

    -- | Does percent-encoding as needed for URI path components.
    escapePath :: String -> String
    escapePath :: String -> String
    escapePath = (Char -> Bool) -> String -> String
    escapeURIString Char -> Bool
    isUnescapedInURIPath
      where isUnescapedInURIPath :: Char -> Bool
    isUnescapedInURIPath Char
    c = Char -> Bool
    isUnescapedInURI Char
    c Bool -> Bool -> Bool
    && Char
    c Char -> String -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` String
    "?#"

    -- | Attempts to reconstruct the absolute URI requested by the client,
    --   including extra path information and query parameters.
    --   If no request URI rewriting is done, or if the web server does not
    --   provide the information needed to reconstruct the request URI,
    --   this function returns the same value as 'queryURI'.
    --
    -- Characters in the components of the returned URI are escaped
    -- when needed, as required by "Network.URI".
    requestURI :: MonadCGI m => m URI
    requestURI :: forall (m :: * -> *). MonadCGI m => m URI
    requestURI =
        do uri <- m URI
    forall (m :: * -> *). MonadCGI m => m URI
    queryURI
           -- Apache sets REQUEST_URI to the original request URI,
           -- with percent-encoding intact.
           mreq <- (>>= parseRelativeReference) <$> getVar "REQUEST_URI"
           return $ case mreq of
                     Maybe URI
    Nothing  -> URI
    uri
                     Just URI
    req -> URI
    uri {
                                      uriPath  = uriPath req,
                                      uriQuery = uriQuery req
                                     }

    --
    -- * Inputs
    --

    -- | Get the value of an input variable, for example from a form.
    --   If the variable has multiple values, the first one is returned.
    --   Example:
    --
    -- > query <- getInput "query"
    getInput :: MonadCGI m =>
                String           -- ^ The name of the variable.
             -> m (Maybe String) -- ^ The value of the variable,
                                 --   or Nothing, if it was not set.
    getInput :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getInput = (Maybe ByteString -> Maybe String)
    -> m (Maybe ByteString) -> m (Maybe String)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((ByteString -> String) -> Maybe ByteString -> Maybe String
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> String
    BS.unpack) (m (Maybe ByteString) -> m (Maybe String))
    -> (String -> m (Maybe ByteString)) -> String -> m (Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe ByteString)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe ByteString)
    getInputFPS

    -- | Like 'getInput', but returns a 'ByteString'.
    getInputFPS :: MonadCGI m =>
                String           -- ^ The name of the variable.
             -> m (Maybe ByteString) -- ^ The value of the variable,
                                 --   or Nothing, if it was not set.
    getInputFPS :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe ByteString)
    getInputFPS = (Maybe Input -> Maybe ByteString)
    -> m (Maybe Input) -> m (Maybe ByteString)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Input -> ByteString) -> Maybe Input -> Maybe ByteString
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Input -> ByteString
    inputValue) (m (Maybe Input) -> m (Maybe ByteString))
    -> (String -> m (Maybe Input)) -> String -> m (Maybe ByteString)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe Input)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe Input)
    getInput_

    -- | Get all the values of an input variable, for example from a form.
    -- This can be used to get all the values from form controls
    -- which allow multiple values to be selected.
    -- Example:
    --
    -- > vals <- getMultiInput "my_checkboxes"
    getMultiInput :: MonadCGI m =>
                     String -- ^ The name of the variable.
                  -> m [String] -- ^ The values of the variable,
                                -- or the empty list if the variable was not set.
    getMultiInput :: forall (m :: * -> *). MonadCGI m => String -> m [String]
    getMultiInput = ([ByteString] -> [String]) -> m [ByteString] -> m [String]
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((ByteString -> String) -> [ByteString] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map ByteString -> String
    BS.unpack) (m [ByteString] -> m [String])
    -> (String -> m [ByteString]) -> String -> m [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m [ByteString]
    forall (m :: * -> *). MonadCGI m => String -> m [ByteString]
    getMultiInputFPS

    -- | Same as 'getMultiInput' but using 'ByteString's.
    getMultiInputFPS :: MonadCGI m =>
                        String -- ^ The name of the variable.
                     -> m [ByteString] -- ^ The values of the variable,
                                -- or the empty list if the variable was not set.
    getMultiInputFPS :: forall (m :: * -> *). MonadCGI m => String -> m [ByteString]
    getMultiInputFPS String
    n = do is <- (CGIRequest -> [(String, Input)]) -> m [(String, Input)]
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> [(String, Input)]
    cgiInputs
                            return [inputValue v | (p,v) <- is, p == n]

    -- | Get the file name of an input.
    getInputFilename :: MonadCGI m =>
                        String           -- ^ The name of the variable.
                     -> m (Maybe String) -- ^ The file name corresponding to the
                                         -- input, if there is one.
    getInputFilename :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getInputFilename = (Maybe Input -> Maybe String)
    -> m (Maybe Input) -> m (Maybe String)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe Input -> (Input -> Maybe String) -> Maybe String
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Input -> Maybe String
    inputFilename) (m (Maybe Input) -> m (Maybe String))
    -> (String -> m (Maybe Input)) -> String -> m (Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe Input)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe Input)
    getInput_

    -- | Get the content-type of an input, if the input exists, e.g. "image\/jpeg".
    --   For non-file inputs, this function returns "text\/plain".
    --   You can use 'parseContentType' to get a structured
    --   representation of the the content-type value.
    getInputContentType :: MonadCGI m =>
                           String   -- ^ The name of the variable.
                        -> m (Maybe String) -- ^ The content type, formatted as a string.
    getInputContentType :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getInputContentType =
        (Maybe Input -> Maybe String)
    -> m (Maybe Input) -> m (Maybe String)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Input -> String) -> Maybe Input -> Maybe String
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (ContentType -> String
    showContentType (ContentType -> String)
    -> (Input -> ContentType) -> Input -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Input -> ContentType
    inputContentType)) (m (Maybe Input) -> m (Maybe String))
    -> (String -> m (Maybe Input)) -> String -> m (Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe Input)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe Input)
    getInput_

    -- | Same as 'getInput', but tries to read the value to the desired type.
    readInput :: (Read a, MonadCGI m) =>
                 String        -- ^ The name of the variable.
              -> m (Maybe a) -- ^ 'Nothing' if the variable does not exist
                               --   or if the value could not be interpreted
                               --   at the desired type.
    readInput :: forall a (m :: * -> *).
    (Read a, MonadCGI m) =>
    String -> m (Maybe a)
    readInput = (Maybe String -> Maybe a) -> m (Maybe String) -> m (Maybe a)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe String -> (String -> Maybe a) -> Maybe a
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> Maybe a
    forall a. Read a => String -> Maybe a
    maybeRead) (m (Maybe String) -> m (Maybe a))
    -> (String -> m (Maybe String)) -> String -> m (Maybe a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getInput

    -- | Get the names and values of all inputs.
    --   Note: the same name may occur more than once in the output,
    --   if there are several values for the name.
    getInputs :: MonadCGI m => m [(String,String)]
    getInputs :: forall (m :: * -> *). MonadCGI m => m [(String, String)]
    getInputs = do is <- (CGIRequest -> [(String, Input)]) -> m [(String, Input)]
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> [(String, Input)]
    cgiInputs
                   return [ (n, BS.unpack (inputValue i)) | (n,i) <- is ]

    -- | Get the names and values of all inputs.
    --   Note: the same name may occur more than once in the output,
    --   if there are several values for the name.
    getInputsFPS :: MonadCGI m => m [(String,ByteString)]
    getInputsFPS :: forall (m :: * -> *). MonadCGI m => m [(String, ByteString)]
    getInputsFPS = do is <- (CGIRequest -> [(String, Input)]) -> m [(String, Input)]
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> [(String, Input)]
    cgiInputs
                      return [ (n, inputValue i) | (n,i) <- is ]

    -- | Get the names of all input variables.
    getInputNames :: MonadCGI m => m [String]
    getInputNames :: forall (m :: * -> *). MonadCGI m => m [String]
    getInputNames = ([String] -> [String]
    sortNub ([String] -> [String])
    -> ([(String, Input)] -> [String]) -> [(String, Input)] -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((String, Input) -> String) -> [(String, Input)] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (String, Input) -> String
    forall a b. (a, b) -> a
    fst) ([(String, Input)] -> [String])
    -> m [(String, Input)] -> m [String]
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` (CGIRequest -> [(String, Input)]) -> m [(String, Input)]
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> [(String, Input)]
    cgiInputs
        where sortNub :: [String] -> [String]
    sortNub = ([String] -> String) -> [[String]] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map [String] -> String
    forall a. HasCallStack => [a] -> a
    head ([[String]] -> [String])
    -> ([String] -> [[String]]) -> [String] -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> [[String]]
    forall a. Eq a => [a] -> [[a]]
    group ([String] -> [[String]])
    -> ([String] -> [String]) -> [String] -> [[String]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> [String]
    forall a. Ord a => [a] -> [a]
    sort

    -- Internal stuff

    getInput_ ::  MonadCGI m => String -> m (Maybe Input)
    getInput_ :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe Input)
    getInput_ String
    n = String -> [(String, Input)] -> Maybe Input
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup String
    n ([(String, Input)] -> Maybe Input)
    -> m [(String, Input)] -> m (Maybe Input)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` (CGIRequest -> [(String, Input)]) -> m [(String, Input)]
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> [(String, Input)]
    cgiInputs

    -- | Get the uninterpreted request body as a String
    getBody :: MonadCGI m => m String
    getBody :: forall (m :: * -> *). MonadCGI m => m String
    getBody = ByteString -> String
    BS.unpack (ByteString -> String) -> m ByteString -> m String
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` (CGIRequest -> ByteString) -> m ByteString
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> ByteString
    cgiRequestBody

    -- | Get the uninterpreted request body as lazy ByteString
    getBodyFPS :: MonadCGI m => m ByteString
    getBodyFPS :: forall (m :: * -> *). MonadCGI m => m ByteString
    getBodyFPS = (CGIRequest -> ByteString) -> m ByteString
    forall a. (CGIRequest -> a) -> m a
    forall (m :: * -> *) a. MonadCGI m => (CGIRequest -> a) -> m a
    cgiGet CGIRequest -> ByteString
    cgiRequestBody

    --
    -- * Cookies
    --

    -- | Get the value of a cookie.
    getCookie :: MonadCGI m =>
                 String           -- ^ The name of the cookie.
              -> m (Maybe String) -- ^ 'Nothing' if the cookie does not exist.
    getCookie :: forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getCookie String
    name = (Maybe String -> Maybe String)
    -> m (Maybe String) -> m (Maybe String)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe String -> (String -> Maybe String) -> Maybe String
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> String -> Maybe String
    findCookie String
    name) (String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getVar String
    "HTTP_COOKIE")

    -- | Same as 'getCookie', but tries to read the value to the desired type.
    readCookie :: (Read a, MonadCGI m) =>
                  String       -- ^ The name of the cookie.
                -> m (Maybe a) -- ^ 'Nothing' if the cookie does not exist
                               --   or if the value could not be interpreted
                               --   at the desired type.
    readCookie :: forall a (m :: * -> *).
    (Read a, MonadCGI m) =>
    String -> m (Maybe a)
    readCookie = (Maybe String -> Maybe a) -> m (Maybe String) -> m (Maybe a)
    forall a b. (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (Maybe String -> (String -> Maybe a) -> Maybe a
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= String -> Maybe a
    forall a. Read a => String -> Maybe a
    maybeRead) (m (Maybe String) -> m (Maybe a))
    -> (String -> m (Maybe String)) -> String -> m (Maybe a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> m (Maybe String)
    forall (m :: * -> *). MonadCGI m => String -> m (Maybe String)
    getCookie

    -- | Set a cookie.
    setCookie :: MonadCGI m => Cookie -> m ()
    setCookie :: forall (m :: * -> *). MonadCGI m => Cookie -> m ()
    setCookie = String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Set-cookie" (String -> m ()) -> (Cookie -> String) -> Cookie -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Cookie -> String
    showCookie

    -- | Delete a cookie from the client
    deleteCookie :: MonadCGI m => Cookie -> m ()
    deleteCookie :: forall (m :: * -> *). MonadCGI m => Cookie -> m ()
    deleteCookie = Cookie -> m ()
    forall (m :: * -> *). MonadCGI m => Cookie -> m ()
    setCookie (Cookie -> m ()) -> (Cookie -> Cookie) -> Cookie -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Cookie -> Cookie
    Cookie.deleteCookie

    --
    -- * Headers
    --

    -- | Add a response header.
    --   Example:
    --
    -- > setHeader "Content-type" "text/plain"
    setHeader :: MonadCGI m =>
                 String -- ^ Header name.
              -> String -- ^ Header value.
              -> m ()
    setHeader :: forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    n = HeaderName -> String -> m ()
    forall (m :: * -> *). MonadCGI m => HeaderName -> String -> m ()
    cgiAddHeader (String -> HeaderName
    HeaderName String
    n)

    -- | Set the HTTP response status.
    setStatus :: MonadCGI m =>
                 Int -- ^  HTTP status code, e.g. @404@
              -> String -- ^ HTTP status message, e.g. @"Not Found"@
              -> m ()
    setStatus :: forall (m :: * -> *). MonadCGI m => Int -> String -> m ()
    setStatus Int
    c String
    m = String -> String -> m ()
    forall (m :: * -> *). MonadCGI m => String -> String -> m ()
    setHeader String
    "Status" (Int -> String
    forall a. Show a => a -> String
    show Int
    c String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    " " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    m)