This module contains functions for writing webservers. These servers process requests in a state monad pipeline and several useful actions are provided here in. See examples/fileserver.hs for an example of how to use this module.
- type Source = IO SourceResult
- data SourceResult
- bsSource :: ByteString -> IO Source
- hSource :: (Int64, Int64) -> Handle -> IO Source
- nullSource :: Source
- type WebMonad = StateT WebState IO
- data WebState
- getRequest :: WebMonad Request
- getReply :: WebMonad Reply
- setReply :: Int -> WebMonad ()
- setHeader :: (Headers -> Headers) -> WebMonad ()
- handleConditionalRequest :: WebMonad ()
- handleHandleToSource :: WebMonad ()
- handleRangeRequests :: WebMonad ()
- handleDecoration :: WebMonad ()
- handleFromFilesystem :: FilePath -> WebMonad ()
- serve :: Int -> WebMonad () -> IO ()
Sources
type Source = IO SourceResultSource
A source is a stream of data, like a lazy data structure, but without
some of the dangers that such entail. A source returns a SourceResult
each time you evaluate it.
data SourceResult Source
SourceError | error - please don't read this source again |
SourceEOF | end of data |
SourceData ByteString | some data |
bsSource :: ByteString -> IO SourceSource
Construct a source from a ByteString
Construct a source from a Handle
A source with no data (e.g. devnull)
The processing monad
Processing a request involve running a number of actions in a StateT monad
where the state for that monad is this record. This contains both a
Source
and a Handle
element. Often something will fill in the Handle
and expect later processing to convert it to a Source
. Somehow, you have
to end up with a Source
, however.
getRequest :: WebMonad RequestSource
Return the request
setReply :: Int -> WebMonad ()Source
Set the current reply to be a reply with the given status code, the default message for that status code, an empty body and an empty set of headers.
setHeader :: (Headers -> Headers) -> WebMonad ()Source
Set a header in the current reply. Because of the way records work, you use this function like this:
setHeader $ \h -> h { httpSomeHeader = Just value }
WebMonad actions
handleConditionalRequest :: WebMonad ()Source
This handles the If-*Matches and If-*Modified conditional headers. It takes its information from the Last-Modified and ETag headers of the current reply. Note that, for the purposes of ETag matching, a reply without an ETag header is considered not to exist from the point of view of, say, If-Matches: *.
handleHandleToSource :: WebMonad ()Source
If the current state includes a Handle, this turns it into a Source
handleRangeRequests :: WebMonad ()Source
This handles Range requests and also translates from Handles to Sources. If the WebMonad has a Handle at this point, then we can construct sources from any subrange of the file. (We also assume that Content-Length is correctly set.)
See RFC 2616, section 14.35
handleDecoration :: WebMonad ()Source
At the moment, this just adds the header Server: Network.MiniHTTP
This is a very simple handler which deals with requests by returning the requested file from the filesystem. It sets a Handle in the state and sets the Content-Type, Content-Length and Last-Modified headers