def add_callback(self, phase, fn):
        """Adds a callback to the context.

        The `phase` determines when and if the callback is executed, and which
        positional arguments are passed in:

        'enter'
          : Called from `rhino.Resource`, after a handler for the current
            request has been resolved, but before the handler is called.

            Arguments: request

        'leave'
          : Called from `rhino.Resource`, after the handler has returned
            successfully.

            Arguments: request, response

        'finalize'
          : Called from `Mapper`, before the WSGI response is finalized.

            Arguments: request, response

        'teardown'
          : Called from `Mapper`, before control is passed back to the
            WSGI layer.

            Arguments: -

        'close'
          : Called when the WSGI server calls `close()` on the response
            iterator.

            Arguments: -

        'teardown' callbacks are guaranteed to be called at the end of every
        request, and are suitable for cleanup tasks like closing database
        handles, etc. If a teardown callback raises an exception, it is
        logged to the server log but does not cause other teardown callbacks
        to be skipped.

        'enter', 'leave' and 'finalize' callbacks are only called if no
        exception occured before they are reached, including exceptions raised
        in other callbacks.

        Whether or not 'close' callbacks are called depends on whether
        a WSGI response could be generated successfully, and if the WSGI
        server calls '.close()' on the returned iterator, as required by the
        spec. If that happens, all 'close' callbacks are called regardless
        of exceptions, like 'teardown' callbacks.
        """
        try:
            self.__callbacks[phase].append(fn)
        except KeyError:
            raise KeyError("Invalid callback phase '%s'. Must be one of %s" % (phase, _callback_phases))