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) |
Safe Haskell | None |
Language | Haskell98 |
Simple Library for writing CGI programs. See http://hoohoo.ncsa.uiuc.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)
- class Monad m => MonadCGI m
- data CGIT m a
- data CGIResult
- type CGI a = CGIT IO a
- class Monad m => MonadIO m where
- liftIO :: MonadIO m => forall a. IO a -> m a
- runCGI :: MonadIO m => CGIT m CGIResult -> m ()
- throwCGI :: (MonadCGI m, MonadThrow m) => SomeException -> m a
- catchCGI :: (MonadCGI m, MonadCatch m) => m a -> (SomeException -> m a) -> m a
- tryCGI :: (Functor m, MonadCGI m, MonadCatch m) => m a -> m (Either SomeException a)
- handleExceptionCGI :: (MonadCGI m, MonadCatch m) => m a -> (SomeException -> m a) -> m a
- handleErrors :: (MonadCGI m, MonadCatch m, MonadIO m) => m CGIResult -> m CGIResult
- logCGI :: MonadIO m => String -> m ()
- output :: MonadCGI m => String -> m CGIResult
- outputFPS :: MonadCGI m => ByteString -> m CGIResult
- outputNothing :: MonadCGI m => m CGIResult
- redirect :: MonadCGI m => String -> m CGIResult
- setHeader :: MonadCGI m => String -> String -> m ()
- setStatus :: MonadCGI m => Int -> String -> m ()
- outputError :: (MonadCGI m, MonadIO m) => Int -> String -> [String] -> m CGIResult
- outputException :: (MonadCGI m, MonadIO m) => SomeException -> m CGIResult
- outputNotFound :: (MonadIO m, MonadCGI m) => String -> m CGIResult
- outputMethodNotAllowed :: (MonadIO m, MonadCGI m) => [String] -> m CGIResult
- outputInternalServerError :: (MonadIO m, MonadCGI m) => [String] -> m CGIResult
- getInput :: MonadCGI m => String -> m (Maybe String)
- getInputFPS :: MonadCGI m => String -> m (Maybe ByteString)
- readInput :: (Read a, MonadCGI m) => String -> m (Maybe a)
- getBody :: MonadCGI m => m String
- getBodyFPS :: MonadCGI m => m ByteString
- getInputs :: MonadCGI m => m [(String, String)]
- getInputsFPS :: MonadCGI m => m [(String, ByteString)]
- getInputNames :: MonadCGI m => m [String]
- getMultiInput :: MonadCGI m => String -> m [String]
- getMultiInputFPS :: MonadCGI m => String -> m [ByteString]
- getInputFilename :: MonadCGI m => String -> m (Maybe String)
- getInputContentType :: MonadCGI m => String -> m (Maybe String)
- getVar :: MonadCGI m => String -> m (Maybe String)
- getVarWithDefault :: MonadCGI m => String -> String -> m String
- getVars :: MonadCGI m => m [(String, String)]
- serverName :: MonadCGI m => m String
- serverPort :: MonadCGI m => m Int
- requestMethod :: MonadCGI m => m String
- pathInfo :: MonadCGI m => m String
- pathTranslated :: MonadCGI m => m String
- scriptName :: MonadCGI m => m String
- queryString :: MonadCGI m => m String
- remoteHost :: MonadCGI m => m (Maybe String)
- remoteAddr :: MonadCGI m => m String
- authType :: MonadCGI m => m (Maybe String)
- remoteUser :: MonadCGI m => m (Maybe String)
- requestContentType :: MonadCGI m => m (Maybe String)
- requestContentLength :: MonadCGI m => m (Maybe Int)
- requestHeader :: MonadCGI m => String -> m (Maybe String)
- progURI :: MonadCGI m => m URI
- queryURI :: MonadCGI m => m URI
- requestURI :: MonadCGI m => m URI
- class Eq a => Acceptable a
- data Accept a
- newtype Charset = Charset String
- newtype ContentEncoding = ContentEncoding String
- newtype Language = Language String
- requestAccept :: MonadCGI m => m (Maybe (Accept ContentType))
- requestAcceptCharset :: MonadCGI m => m (Maybe (Accept Charset))
- requestAcceptEncoding :: MonadCGI m => m (Maybe (Accept ContentEncoding))
- requestAcceptLanguage :: MonadCGI m => m (Maybe (Accept Language))
- negotiate :: Acceptable a => [a] -> Maybe (Accept a) -> [a]
- data ContentType :: * = ContentType {}
- showContentType :: ContentType -> String
- parseContentType :: Monad m => String -> m ContentType
- data Cookie = Cookie {}
- newCookie :: String -> String -> Cookie
- getCookie :: MonadCGI m => String -> m (Maybe String)
- readCookie :: (Read a, MonadCGI m) => String -> m (Maybe a)
- setCookie :: MonadCGI m => Cookie -> m ()
- deleteCookie :: MonadCGI m => Cookie -> m ()
- formEncode :: [(String, String)] -> String
- urlEncode :: String -> String
- formDecode :: String -> [(String, String)]
- urlDecode :: String -> String
- module Network.CGI.Compat
CGI monad
class Monad m => MonadCGI m Source
The class of CGI monads. Most CGI actions can be run in any monad which is an instance of this class, which means that you can use your own monad transformers to add extra functionality.
The CGIT monad transformer.
MonadTrans CGIT | |
MonadCatch m => MonadError SomeException (CGIT m) | |
Monad m => Monad (CGIT m) | |
(Functor m, Monad m) => Functor (CGIT m) | |
(Applicative m, Monad m) => Applicative (CGIT m) | |
MonadThrow m => MonadThrow (CGIT m) | |
MonadCatch m => MonadCatch (CGIT m) | |
MonadMask m => MonadMask (CGIT m) | |
MonadIO m => MonadIO (CGIT m) | |
Monad m => MonadCGI (CGIT m) | |
Typeable ((* -> *) -> * -> *) CGIT |
The result of a CGI program.
class Monad m => MonadIO m where
Monads in which IO
computations may be embedded.
Any monad built by applying a sequence of monad transformers to the
IO
monad will be an instance of this class.
Instances should satisfy the following laws, which state that liftIO
is a transformer of monads:
MonadIO IO | |
MonadIO m => MonadIO (ListT m) | |
MonadIO m => MonadIO (MaybeT m) | |
MonadIO m => MonadIO (IdentityT m) | |
MonadIO m => MonadIO (CGIT m) | |
MonadIO m => MonadIO (ContT r m) | |
MonadIO m => MonadIO (ReaderT r m) | |
MonadIO m => MonadIO (StateT s m) | |
MonadIO m => MonadIO (StateT s m) | |
MonadIO m => MonadIO (ExceptT e m) | |
(Error e, MonadIO m) => MonadIO (ErrorT e m) | |
(Monoid w, MonadIO m) => MonadIO (WriterT w m) | |
(Monoid w, MonadIO m) => MonadIO (WriterT w m) | |
MonadIO m => MonadIO (ParsecT s u m) | |
(Monoid w, MonadIO m) => MonadIO (RWST r w s m) | |
(Monoid w, MonadIO m) => MonadIO (RWST r w s m) |
runCGI :: MonadIO m => CGIT m CGIResult -> m () Source
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.
Error handling
throwCGI :: (MonadCGI m, MonadThrow m) => SomeException -> m a Source
Throw an exception in a CGI monad. The monad is required to be
a MonadThrow
, so that we can use throwM
to guarantee ordering.
catchCGI :: (MonadCGI m, MonadCatch m) => m a -> (SomeException -> m a) -> m a Source
Catches any expection thrown by a CGI action, and uses the given exception handler if an exception is thrown.
tryCGI :: (Functor m, MonadCGI m, MonadCatch m) => m a -> m (Either SomeException a) Source
Catches any exception thrown by an CGI action, and returns either the exception, or if no exception was raised, the result of the action.
handleExceptionCGI :: (MonadCGI m, MonadCatch m) => m a -> (SomeException -> m a) -> m a Source
handleErrors :: (MonadCGI m, MonadCatch m, MonadIO m) => m CGIResult -> m CGIResult Source
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)
Logging
logCGI :: MonadIO m => String -> m () Source
Logs some message using the server's logging facility. FIXME: does this have to be more general to support FastCGI etc? Maybe we should store log messages in the CGIState?
Output
:: MonadCGI m | |
=> ByteString | The string to output. |
-> m CGIResult |
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
.
outputNothing :: MonadCGI m => m CGIResult Source
Do not output anything (except headers).
Redirect to some location.
Add a response header. Example:
setHeader "Content-type" "text/plain"
Set the HTTP response status.
Error pages
:: (MonadCGI m, MonadIO m) | |
=> Int | HTTP Status code |
-> String | Status message |
-> [String] | Error information |
-> m CGIResult |
Output an error page to the user, with the given
HTTP status code in the response. Also logs the error information
using logCGI
.
outputException :: (MonadCGI m, MonadIO m) => SomeException -> m CGIResult Source
Output a 500 Internal Server Error with information from
an Exception
.
Use outputError
to output and log a 404 Not Found error.
Use outputError
to output and log a 405 Method Not Allowed error.
outputInternalServerError Source
Use outputError
to output and log a 500 Internal Server Error.
Input
:: MonadCGI m | |
=> String | The name of the variable. |
-> m (Maybe String) | The value of the variable, or Nothing, if it was not set. |
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"
:: MonadCGI m | |
=> String | The name of the variable. |
-> m (Maybe ByteString) | The value of the variable, or Nothing, if it was not set. |
Like getInput
, but returns a ByteString
.
:: (Read a, MonadCGI m) | |
=> String | The name of the variable. |
-> m (Maybe a) |
|
Same as getInput
, but tries to read the value to the desired type.
getBodyFPS :: MonadCGI m => m ByteString Source
Get the uninterpreted request body as lazy ByteString
getInputs :: MonadCGI m => m [(String, String)] Source
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)] Source
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.
getInputNames :: MonadCGI m => m [String] Source
Get the names of all input variables.
:: 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. |
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"
:: 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. |
Same as getMultiInput
but using ByteString
s.
:: MonadCGI m | |
=> String | The name of the variable. |
-> m (Maybe String) | The file name corresponding to the input, if there is one. |
Get the file name of an input.
:: MonadCGI m | |
=> String | The name of the variable. |
-> m (Maybe String) | The content type, formatted as a string. |
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.
Environment
Get the value of a CGI environment variable. Example:
remoteAddr <- getVar "REMOTE_ADDR"
getVars :: MonadCGI m => m [(String, String)] Source
Get all CGI environment variables and their values.
Request information
serverName :: MonadCGI m => m String Source
The server's hostname, DNS alias, or IP address as it would appear in self-referencing URLs.
serverPort :: MonadCGI m => m Int Source
The port number to which the request was sent.
requestMethod :: MonadCGI m => m String Source
The method with which the request was made. For HTTP, this is "GET", "HEAD", "POST", etc.
pathInfo :: MonadCGI m => m String Source
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.
pathTranslated :: MonadCGI m => m String Source
The path returned by pathInfo
, but with virtual-to-physical
mapping applied to it.
scriptName :: MonadCGI m => m String Source
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.
queryString :: MonadCGI m => m String Source
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.
remoteHost :: MonadCGI m => m (Maybe String) Source
The hostname making the request. If the server does not have
this information, Nothing is returned. See also remoteAddr
.
remoteAddr :: MonadCGI m => m String Source
The IP address of the remote host making the request.
authType :: MonadCGI m => m (Maybe String) Source
If the server supports user authentication, and the script is protected, this is the protocol-specific authentication method used to validate the user.
remoteUser :: MonadCGI m => m (Maybe String) Source
If the server supports user authentication, and the script is protected, this is the username they have authenticated as.
requestContentType :: MonadCGI m => m (Maybe String) Source
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.
requestContentLength :: MonadCGI m => m (Maybe Int) Source
For queries which have attached information, such as HTTP POST and PUT, this is the length of the content given by the client.
requestHeader :: MonadCGI m => String -> m (Maybe String) Source
Gets the value of the request header with the given name. The header name is case-insensitive. Example:
requestHeader "User-Agent"
Program and request URI
progURI :: MonadCGI m => m URI Source
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.
queryURI :: MonadCGI m => m URI Source
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.
requestURI :: MonadCGI m => m URI Source
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.
Content negotiation
class Eq a => Acceptable a Source
includes, top
Show a => Show (Accept a) | |
HeaderValue a => HeaderValue (Accept a) |
newtype ContentEncoding Source
requestAccept :: MonadCGI m => m (Maybe (Accept ContentType)) Source
requestAcceptEncoding :: MonadCGI m => m (Maybe (Accept ContentEncoding)) Source
negotiate :: Acceptable a => [a] -> Maybe (Accept a) -> [a] Source
Content type
data ContentType :: *
A MIME media type value.
The Show
instance is derived automatically.
Use showContentType
to obtain the standard
string representation.
See http://www.ietf.org/rfc/rfc2046.txt for more
information about MIME media types.
ContentType | |
|
showContentType :: ContentType -> String
parseContentType :: Monad m => String -> m ContentType
Parse the standard representation of a content-type.
If the input cannot be parsed, this function calls
fail
with a (hopefully) informative error message.
Cookies
Contains all information about a cookie set by the server.
Cookie | |
|
Construct a cookie with only name and value set. This client will expire when the browser sessions ends, will only be sent to the server and path which set it and may be sent using any means.
:: MonadCGI m | |
=> String | The name of the cookie. |
-> m (Maybe String) |
|
Get the value of a cookie.
:: (Read a, MonadCGI m) | |
=> String | The name of the cookie. |
-> m (Maybe a) |
|
Same as getCookie
, but tries to read the value to the desired type.
deleteCookie :: MonadCGI m => Cookie -> m () Source
Delete a cookie from the client
URL encoding
formEncode :: [(String, String)] -> String Source
Formats name-value pairs as application/x-www-form-urlencoded.
urlEncode :: String -> String Source
Converts a single value to the application/x-www-form-urlencoded encoding.
formDecode :: String -> [(String, String)] Source
Gets the name-value pairs from application/x-www-form-urlencoded data.
urlDecode :: String -> String Source
Converts a single value from the application/x-www-form-urlencoded encoding.
Compatibility with the old API
module Network.CGI.Compat