Introduction
************

The RedirectResource is a simple resource implementation that
redirects the client to another URL.

The example web service implements the CookbookSetTraverse class to
serve a RedirectResource at /cookbooks/featured. This particular
RedirectResource redirects you to the currently featured cookbook.

    >>> from lazr.restful.testing.webservice import WebServiceCaller
    >>> webservice = WebServiceCaller(domain='cookbooks.dev')

    >>> print webservice.get("/cookbooks/featured")
    HTTP/1.1 301 Moved Permanently
    ...
    Location: http://.../cookbooks/Mastering%20the%20Art%20of%20French%20Cooking
    ...

The redirect has an extra twist when the resource was requested from a
web browser as opposed to a web service client. When a web browser
follows a redirect, it does not re-send the Accept header from the
original request. This can lead to lazr.restful serving the wrong
representation (usually HTML instead of JSON). To avoid this problem,
lazr.restful sends the original Accept header in the redirect URL
itself, so it can look it up when the browser follows the redirect.

    >>> from lazr.restful.testing.webservice import (
    ...     WebServiceAjaxCaller)
    >>> ajax = WebServiceAjaxCaller(domain='cookbooks.dev')
    >>> print ajax.get("/cookbooks/featured")
    HTTP/1.1 301 Moved Permanently
    ...
    Location: http://.../cookbooks/Mastering%20the%20Art%20of%20French%20Cooking?ws.accept=application/json
    ...

    >>> print ajax.get(
    ...     "/cookbooks/featured",
    ...     headers=dict(Accept="application/xhtml+xml"))
    HTTP/1.1 301 Moved Permanently
    ...
    Location: http://...?ws.accept=application/xhtml%2Bxml
    ...

The redirect works even if the redirect URI contains characters not
valid in URIs. In this case, the redirect is to a URL that contains
curly braces (see traversal.py for details).

    >>> print ajax.get("/cookbooks/featured-invalid")
    HTTP/1.1 301 Moved Permanently
    ...
    Location: http://.../Mastering%20the%20Art%20of%20French%20Cooking{invalid}?ws.accept=application/json
    ...
