- data Request
- data Response
- type ServerPart a = ServerPartT IO a
- data ServerConfig = ServerConfig {}
- defaultServerConfig :: ServerConfig
- serve :: Maybe ServerConfig -> ServerPart Response -> IO ()
- method :: MatchMethod method => method -> ServerPart ()
- data Method
- class MatchMethod m where
- matchMethod :: m -> Method -> Bool
- dir :: String -> ServerPart a -> ServerPart a
- path :: FromReqURI a => (a -> ServerPart b) -> ServerPart b
- class FromReqURI a where
- fromReqURI :: String -> Maybe a
- nullDir :: ServerPart ()
- guardRq :: (Request -> Bool) -> ServerPart ()
- class ToMessage a where
- toContentType :: a -> ByteString
- toMessage :: a -> ByteString
- toResponse :: a -> Response
- toResponseBS :: ByteString -> ByteString -> Response
- ok :: a -> ServerPart a
- internalServerError :: a -> ServerPart a
- unauthorized :: a -> ServerPart a
- notFound :: a -> ServerPart a
- seeOther :: ToSURI uri => uri -> a -> ServerPart a
- setResponseCode :: Int -> ServerPart ()
- lookBS :: String -> ServerPart ByteString
- lookBSs :: String -> ServerPart [ByteString]
- lookText :: String -> ServerPart Text
- lookTexts :: String -> ServerPart [Text]
- lookFile :: String -> ServerPart (FilePath, FilePath, ContentType)
- data ContentType = ContentType {}
- data Cookie = Cookie {
- cookieVersion :: String
- cookiePath :: String
- cookieDomain :: String
- cookieName :: String
- cookieValue :: String
- secure :: Bool
- httpOnly :: Bool
- data CookieLife
- mkCookie :: String -> String -> Cookie
- addCookies :: [(CookieLife, Cookie)] -> ServerPart ()
- expireCookie :: String -> ServerPart ()
- lookCookieValue :: String -> ServerPart String
- addHeaderM :: String -> String -> ServerPart ()
- setHeaderM :: String -> String -> ServerPart ()
- getHeaderM :: String -> ServerPart (Maybe ByteString)
- data Browsing
- serveDirectory :: Browsing -> [FilePath] -> FilePath -> ServerPart Response
- serveFile :: (FilePath -> ServerPart String) -> FilePath -> ServerPart Response
- asContentType :: String -> FilePath -> IO String
- class Monad m => MonadPlus m where
- msum :: MonadPlus m => [m a] -> m a
Core Types
data Response
an HTTP Response
type ServerPart a = ServerPartT IO a
An alias for ServerPartT
IO
Starting the Server
data ServerConfig Source
configuration to be used with serve
function
defaultServerConfig :: ServerConfigSource
a reasonable default ServerConfig
ServerConfig { port = 8000 , ramQuota = 1 * 10^6 , diskQuota = 20 * 10^6 , tmpDir = "/tmp/" }
:: Maybe ServerConfig | if Nothing, then use |
-> ServerPart Response | request handler |
-> IO () |
start the server and handle requests using the supplied ServerPart
Routing an Incoming Request
method :: MatchMethod method => method -> ServerPart ()Source
Guard against the request method
Example:
handler :: ServerPart Response handler = do method [GET, HEAD] ...
data Method
log access requests using hslogger and apache-style log formatting
see also: Conf
HTTP request method
class MatchMethod m where
instances of this class provide a variety of ways to match on the Request
method.
Examples
method GET -- match GET method [HEAD, GET] -- match HEAD or GET method (not . (==) DELETE) -- match any method except DELETE method () -- match any method
matchMethod :: m -> Method -> Bool
MatchMethod () | |
MatchMethod Method | |
MatchMethod [Method] | |
MatchMethod (Method -> Bool) |
dir :: String -> ServerPart a -> ServerPart aSource
Pop a path element and run the supplied handler if it matches the given string.
handler :: ServerPart Response handler = dir "foo" $ dir "bar" $ subHandler
The path element can not contain '/'. See also dirs
.
path :: FromReqURI a => (a -> ServerPart b) -> ServerPart bSource
Pop a path element and parse it using the fromReqURI
in the
FromReqURI
class.
class FromReqURI a where
This class is used by path
to parse a path component into a
value.
The instances for number types (Int
, Float
, etc) use readM
to
parse the path component.
The instance for String
, on the other hand, returns the
unmodified path component.
See the following section of the Happstack Crash Course for
detailed instructions using and extending FromReqURI
:
http://www.happstack.com/docs/crashcourse/RouteFilters.html#FromReqURI
fromReqURI :: String -> Maybe a
nullDir :: ServerPart ()Source
guard which only succeeds if there are no remaining path segments
Often used if you want to explicitly assign a route for /
guardRq :: (Request -> Bool) -> ServerPart ()Source
Guard using an arbitrary function on the Request
.
Creating a Response
class ToMessage a where
toResponse
will convert a value into a Response
body,
set the content-type
, and set the default response code for that type.
Example:
main = simpleHTTP nullConf $ toResponse "hello, world!"
will generate a Response
with the content-type text/plain
,
the response code 200 OK
, and the body: hello, world!
.
simpleHTTP
will call toResponse
automatically, so the above can be shortened to:
main = simpleHTTP nullConf $ "hello, world!"
Minimal definition: toMessage
(and usually toContentType
).
:: ByteString | content-type |
-> ByteString | response body |
-> Response |
A low-level function to build a Response
from a content-type
and a ByteString
.
Creates a Response
in a manner similar to the ToMessage
class,
but without requiring an instance declaration.
example:
import Data.ByteString.Char8 as C import Data.ByteString.Lazy.Char8 as L import Happstack.Lite main = serve Nothing $ ok $ toResponseBS (C.pack "text/plain") (L.pack "hello, world")
(note: C.pack
and L.pack
only work for ascii. For unicode strings you would need to use utf8-string
, text
, or something similar to create a valid ByteString
).
Setting the Response Code
ok :: a -> ServerPart aSource
Respond with 200 OK
.
main = serve Nothing $ ok "Everything is OK"
internalServerError :: a -> ServerPart aSource
Respond with 500 Internal Server Error
.
main = serve Nothing $ internalServerError "Sorry, there was an internal server error."
unauthorized :: a -> ServerPart aSource
Respond with 401 Unauthorized
.
main = serve Nothing $ unauthorized "You are not authorized."
notFound :: a -> ServerPart aSource
Respond with 404 Not Found
.
main = serve Nothing $ notFound "What you are looking for has not been found."
seeOther :: ToSURI uri => uri -> a -> ServerPart aSource
Respond with 303 See Other
.
main = serve Nothing $ seeOther "http://example.org/" "What you are looking for is now at http://example.org/"
NOTE: The second argument of seeOther
is the message body which will sent to the browser. According to the HTTP 1.1 spec,
the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).
This is because pre-HTTP/1.1 user agents do not support 303. However, in practice you can probably just use ""
as the second argument.
:: Int | response code |
-> ServerPart () |
Looking up Request Parameters
lookBS :: String -> ServerPart ByteStringSource
Gets the first matching named input parameter as a lazy ByteString
Searches the QUERY_STRING followed by the Request body.
see also: lookBSs
lookBSs :: String -> ServerPart [ByteString]Source
Gets all matches for the named input parameter as lazy ByteString
s
Searches the QUERY_STRING followed by the Request body.
see also: lookBS
lookText :: String -> ServerPart TextSource
lookTexts :: String -> ServerPart [Text]Source
:: String | name of input field to search for |
-> ServerPart (FilePath, FilePath, ContentType) | (temporary file location, uploaded file name, content-type) |
Gets the first matching named file
Files can only appear in the request body. Additionally, the form must set enctype="multipart/form-data".
This function returns a tuple consisting of:
- The temporary location of the uploaded file
- The local filename supplied by the browser
- The content-type supplied by the browser
NOTE: You must move the file from the temporary location before the
Response
is sent. The temporary files are automatically removed
after the Response
is sent.
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 | |
|
Cookies
data Cookie
a type for HTTP cookies. Usually created using mkCookie
.
Cookie | |
|
data CookieLife
Specify the lifetime of a cookie.
Note that we always set the max-age and expires headers because
internet explorer does not honor max-age. You can specific MaxAge
or Expires
and the other will be calculated for you. Choose which
ever one makes your life easiest.
Creates a cookie with a default version of 1, empty domain, a path of /, secure == False and httpOnly == False
see also: addCookie
addCookies :: [(CookieLife, Cookie)] -> ServerPart ()Source
expireCookie :: String -> ServerPart ()Source
Expire the named cookie immediately and set the cookie value to ""
main = serve Nothing $ do expireCookie "name" ok $ "The cookie has been expired."
lookCookieValue :: String -> ServerPart StringSource
gets the named cookie as a string
HTTP Headers
addHeaderM :: String -> String -> ServerPart ()Source
Add headers into the response. This method does not overwrite
any existing header of the same name, hence the name addHeaderM
.
If you want to replace a header use setHeaderM
.
setHeaderM :: String -> String -> ServerPart ()Source
Set a header into the response. This will replace an existing
header of the same name. Use addHeaderM
if you want to add more
than one header of the same name.
getHeaderM :: String -> ServerPart (Maybe ByteString)Source
Get a header out of the request.
File Serving
data Browsing
see serveDirectory
:: Browsing | allow directory browsing |
-> [FilePath] | index file names, in case the requested path is a directory |
-> FilePath | file/directory to serve |
-> ServerPart Response |
Serve files and directories from a directory and its subdirectories using sendFile
.
Usage:
serveDirectory EnableBrowsing ["index.html"] "path/to/files/on/disk"
If the requested path does not match a file or directory on the
disk, then serveDirectory
calls mzero
.
If the requested path is a file then the file is served normally.
If the requested path is a directory, then the result depends on what the first two arguments to the function are.
The first argument controls whether directory browsing is enabled.
The second argument is a list of index files (such as index.html).
When a directory is requested, serveDirectory
will first try to
find one of the index files (in the order they are listed). If that
fails, it will show a directory listing if EnableBrowsing
is set,
otherwise it will return forbidden "Directory index forbidden"
.
Here is an explicit list of all the possible outcomes when the argument is a (valid) directory:
DisableBrowsing
, empty index file list
This will always return, forbidden "Directory index forbidden"
DisableBrowsing
, non-empty index file list
- If an index file is found it will be shown.
- Otherwise returns, forbidden "Directory index forbidden"
EnableBrowsing
, empty index file list
Always shows a directory index.
EnableBrowsing
, non-empty index file list
- If an index file is found it will be shown
- Otherwise shows a directory index
see also: defaultIxFiles
, serveFile
:: (FilePath -> ServerPart String) | function for determining content-type of file. Typically |
-> FilePath | path to the file to serve |
-> ServerPart Response |
Serve a single, specified file. The name of the file being served is specified explicity. It is not derived automatically from the Request
url.
example 1:
Serve as a specific content-type:
serveFile (asContentType "image/jpeg") "/srv/data/image.jpg"
example 2:
Serve guessing the content-type from the extension:
serveFile (guessContentTypeM mimeTypes) "/srv/data/image.jpg"
If the specified path does not exist or is not a file, this function will return mzero
.
WARNING: No security checks are performed.
NOTE: alias for serveFileUsing
filePathSendFile