-*- mode: markup; -*-

* Handlers

Toot’s main job, as a web server, is to accept a connection from an
HTTP client, read and parse the request, and return a reply generated
by some user-provided code, a \i{handler}.

Before it hands off to the handler, Toot has to deal with a bunch of
gorp involving persistent connections, parsing the request, chunking
output, etc. But that should all be of little to no concern of the
user who just provides a handler that knows what to do with the
requests when they’re available.

A \i{handler} is any object that can be passed as the first argument
to the generic function \code{handle-request}:

   (defgeneric handle-request (handler request))

Out of the box, Toot, defines methods specializing the \code{handler}
parameter on \code{function} and \code{symbol}, which just turn around
and funcall the handler one argument, the \code{request}.

A handler has four choices of how it can handle a request.

  - It can return a string which will be properly encoded (based on
    the values of content-type and charset set on the request object)
    and sent as the body of the reply.

  - It can call \code{send-headers} on the request which will return a
    stream to which it can then write the body of the reply. In this
    case any outgoing headers such as content-type and outgoing
    cookies need to be set before calling send-headers.

  - It can call \code{abort-request-handler} with an HTTP status code,
    usually >= 300 which will cause the server to send an appropriate
    reply to the client. (This is used for both errors, e.g. 404: Not
    found, and also thing like redirects, e.g. 301: Moved permanently.)

  - It can return the symbol \code{not-handled}. If the handler called
    directly by Toot returns \code{not-handled}, the server will send
    a \code{404: Not found} reply. But a composite handler could use
    that return value as an indication to try another handler.

* Functions useful in handlers

** Request data

request-uri

request-method

get-parameter

post-parameter

parameter

header-in

cookie-in

remote-addr

remote-port

authorization — gets the username and password provided via basic HTTP auth.

host

user-agent

referer

** For controlling reply — low level

send-headers — causes the HTTP headers to be sent and returns a stream
to which the body of the reply can be written.

set-cookie

(setf return-code)

(setf content-length)

(setf content-type)

(setf charset)

(setf response-header)

** For controlling reply — high-level

serve-file — serve up a specific file. Handles If-Modified-Since and
Range requests. Guesses at Content-Type based on extension if not
supplied. Sends “404: Not Found” reply if file does not exist.

no-cache — add headers to the reply which should prevent caching by
the browser.

redirect — send a redirect rather than generating a reply.

require-authorization — sends “401: Authorization Required” headers requiring basic HTTP
authentication.

handle-if-modified-since — sends a “304: Not Modified” reply if the time
provided is the same as the time provided in the request.

handle-range — compute the starting position and number of bytes to
send. Send a “416: Requested range not satisfiable” if the range is
invalid.

** Misc

log-message — log a message to Toot’s message log.

maybe-handle — macro for writing composable handlers.
