Handlers
========

Handlers are functions that have the general signature::

  handler(request, response)

It is expected that the handler will use information from
the request (e.g. the path) either to populate the response
object with the data to send, or to directly write to the
output stream via the ResponseWriter instance associated with
the request. If a handler writes to the output stream then the
server will not attempt additional writes, i.e. the choice to write
directly in the handler or not is all-or-nothing.

A number of general-purpose handler functions are provided by default:

.. _handlers.Python:

Python Handlers
---------------

Python handlers are functions which provide a higher-level API over
manually updating the response object, by causing the return value of
the function to provide (part of) the response. There are three
possible sets of values that may be returned::


  (status, headers, content)
  (headers, content)
  content

Here `status` is either a tuple (status code, message) or simply a
integer status code, `headers` is a list of (field name, value) pairs,
and `content` is a string or an iterable returning strings. Such a
function may also update the response manually. For example one may
use `response.headers.set` to set a response header, and only return
the content. One may even use this kind of handler, but manipulate
the output socket directly, in which case the return value of the
function, and the properties of the response object, will be ignored.

The most common way to make a user function into a python handler is
to use the provided `wptserve.handlers.handler` decorator::

  from wptserve.handlers import handler

  @handler
  def test(request, response):
      return [("X-Test": "PASS"), ("Content-Type", "text/plain")], "test"

  #Later, assuming we have a Router object called 'router'

  router.register("GET", "/test", test)

JSON Handlers
-------------

This is a specialisation of the python handler type specifically
designed to facilitate providing JSON responses. The API is largely
the same as for a normal python handler, but the `content` part of the
return value is JSON encoded, and a default Content-Type header of
`application/json` is added. Again this handler is usually used as a
decorator::

  from wptserve.handlers import json_handler

  @json_handler
  def test(request, response):
      return {"test": "PASS"}

Python File Handlers
--------------------

Python file handlers are designed to provide a vaguely PHP-like interface
where each resource corresponds to a particular python file on the
filesystem. Typically this is hooked up to a route like ``("*",
"*.py", python_file_handler)``, meaning that any .py file will be
treated as a handler file (note that this makes python files unsafe in
much the same way that .php files are when using PHP).

Unlike PHP, the python files don't work by outputting text to stdout
from the global scope. Instead they must define a single function
`main` with the signature::

  main(request, response)

This function then behaves just like those described in
:ref:`handlers.Python` above.

asis Handlers
-------------

These are used to serve files as literal byte streams including the
HTTP status line, headers and body. In the default configuration this
handler is invoked for all files with a .asis extension.

File Handlers
-------------

File handlers are used to serve static files. By default the content
type of these files is set by examining the file extension. However
this can be overridden, or additional headers supplied, by providing a
file with the same name as the file being served but an additional
.headers suffix, i.e. test.html has its headers set from
test.html.headers. The format of the .headers file is plaintext, with
each line containing::

  Header-Name: header_value

In addition headers can be set for a whole directory of files (but not
subdirectories), using a file called `__dir__.headers`.
