| 1 |
<?xml version="1.0" encoding="UTF-8"?> |
|---|
| 2 |
<section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" |
|---|
| 3 |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="designchoices"> |
|---|
| 4 |
<title>Design choices</title> |
|---|
| 5 |
<section> |
|---|
| 6 |
<title>A layered API</title> |
|---|
| 7 |
<section> |
|---|
| 8 |
<title>Simple apps should not require any knowledge of HTTP</title> |
|---|
| 9 |
<para>At its most basic, CherryPy is designed to allow the production of simple websites |
|---|
| 10 |
without having to think about any of the details of HTTP. Notice we're saying HTTP (the |
|---|
| 11 |
transport), not HTML (the markup language)! In particular, developers should not have to |
|---|
| 12 |
concern themselves with:</para> |
|---|
| 13 |
<itemizedlist> |
|---|
| 14 |
<listitem> |
|---|
| 15 |
<para>Responding to unpublished requests</para> |
|---|
| 16 |
</listitem> |
|---|
| 17 |
<listitem> |
|---|
| 18 |
<para>Logging and notifying users appropriately when unhandled exceptions |
|---|
| 19 |
occur</para> |
|---|
| 20 |
</listitem> |
|---|
| 21 |
<listitem> |
|---|
| 22 |
<para>The difference between query strings and POSTed params</para> |
|---|
| 23 |
</listitem> |
|---|
| 24 |
<listitem> |
|---|
| 25 |
<para>The decoding and unpacking of request headers and bodies, including file |
|---|
| 26 |
uploads</para> |
|---|
| 27 |
</listitem> |
|---|
| 28 |
<listitem> |
|---|
| 29 |
<para>Response status or headers</para> |
|---|
| 30 |
</listitem> |
|---|
| 31 |
</itemizedlist> |
|---|
| 32 |
<para>For the most part, simple "page handlers" (functions attached to |
|---|
| 33 |
<code>cherrypy.root</code>), should never have to refer to cherrypy at all! They receive |
|---|
| 34 |
params via function arguments, and return content directly. Advanced functionality is |
|---|
| 35 |
most often enabled via the built-in filters, which encapsulate the particulars of HTTP, |
|---|
| 36 |
and can be completely controlled via the config file.</para> |
|---|
| 37 |
</section> |
|---|
| 38 |
<section> |
|---|
| 39 |
<title>Advanced apps should have full control over (valid) HTTP output</title> |
|---|
| 40 |
<para>Simple apps are produced simply, but when a developer needs to step out of the |
|---|
| 41 |
mundane and provide real value, they should be able to leverage the complete power and |
|---|
| 42 |
flexibility of the HTTP specification. In general, the HTTP request and response messages |
|---|
| 43 |
are completely represented in the <code>cherrypy.request</code> and |
|---|
| 44 |
<code>.response</code> objects. At the lowest level, a developer should be able to |
|---|
| 45 |
generate any valid HTTP response message by modifying |
|---|
| 46 |
<code>cherrypy.response.status</code>, <code>.headers</code>, and/or |
|---|
| 47 |
<code>.body</code>.</para> |
|---|
| 48 |
<section> |
|---|
| 49 |
<title>How CherryPy relates to REST (REpresentational State Transfer)</title> |
|---|
| 50 |
<para>The design of HTTP itself is guided by REST, a set of principles which |
|---|
| 51 |
constrain its expressivity and therefore its implementation. HTTP is a transfer |
|---|
| 52 |
protocol which enables the exchange of representations of resources. In a RESTful |
|---|
| 53 |
design, clients never expect to access a resource directly; instead, they request a |
|---|
| 54 |
representation of that resource. For example, if a resource has both an XML and an |
|---|
| 55 |
HTML representation, then an HTTP/1.1 server might be expected to inspect the Accept |
|---|
| 56 |
request header in order to decide which representation to serve in response.</para> |
|---|
| 57 |
<para>It's important to clarify some terminology, here. In <ulink |
|---|
| 58 |
url="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">REST terms</ulink>, |
|---|
| 59 |
a "resource" is "any concept that might be the target of an author’s hypertext |
|---|
| 60 |
reference...a conceptual mapping to a set of entities, not the entity that |
|---|
| 61 |
corresponds to the mapping at any particular point in time". A resource is not the |
|---|
| 62 |
request, nor the response, in an HTTP conversation. "The resource is not the storage |
|---|
| 63 |
object. The resource is not a mechanism that the server uses to handle the storage |
|---|
| 64 |
object. The resource is a conceptual mapping — the server receives the identifier |
|---|
| 65 |
(which identifies the mapping) and applies it to its current mapping implementation |
|---|
| 66 |
(usually a combination of collection-specific deep tree traversal and/or hash tables) |
|---|
| 67 |
to find the currently responsible handler implementation and the handler |
|---|
| 68 |
implementation then selects the appropriate action+response based on the request |
|---|
| 69 |
content."</para> |
|---|
| 70 |
<para>CherryPy, therefore, does not provide REST resources, nor model them, nor serve |
|---|
| 71 |
them. Instead, it provides mappings between identifiers (URI's) and handlers |
|---|
| 72 |
(functions). It allows application developers to model resources, perhaps, but it |
|---|
| 73 |
only serves representations of resources.</para> |
|---|
| 74 |
<para>By default, these identifier-to-handler mappings (which we will call "handler |
|---|
| 75 |
dispatch" from now on) follow a simple pattern: since the path portion of a URI is |
|---|
| 76 |
hierarchical, CherryPy arranges handlers in a similar heirarchy, starting at |
|---|
| 77 |
cherrypy.root, and branching on each attribute; every leaf node in this tree must be |
|---|
| 78 |
"exposed" (but the branches need not be, see section 2.2). Note in particular that, |
|---|
| 79 |
although the query portion of a Request-URI is part of the resource identifier, |
|---|
| 80 |
CherryPy does not use it to map identifiers to handlers. Application developers may |
|---|
| 81 |
use the query string to further identify the requested resource, of course, but |
|---|
| 82 |
CherryPy, not having any domain-specific knowledge about the format or semantic of a |
|---|
| 83 |
query string, doesn't try to guess.</para> |
|---|
| 84 |
<para>Filters, then, are CherryPy's way to wrap or circumvent the default handler |
|---|
| 85 |
dispatch. EncodingFilter, for example, wraps the response from a handler, encoding |
|---|
| 86 |
the response body as it is produced. StaticFilter, on the other hand, intercepts some |
|---|
| 87 |
requests (based on the path portion of the Request-URI) and implements its own |
|---|
| 88 |
identifier-to-handler mapping. Developers who wish to provide their own handler |
|---|
| 89 |
dispatch mechanisms are encouraged to do so via a filter.</para> |
|---|
| 90 |
</section> |
|---|
| 91 |
</section> |
|---|
| 92 |
</section> |
|---|
| 93 |
</section> |
|---|