Skip to content

Commit

Permalink
doc: Add FAQ
Browse files Browse the repository at this point in the history
This patch introduces a new FAQ, and adds some FAQ-like info inline
to doctrings where appropriate. NOTES.md is no longer necessary now
that we have its content properly documented, and so it was removed.
  • Loading branch information
kgriffs committed Apr 15, 2014
1 parent b0167f4 commit 49604c1
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 46 deletions.
33 changes: 0 additions & 33 deletions NOTES.md

This file was deleted.

4 changes: 2 additions & 2 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

# General information about the project.
project = u'Falcon'
copyright = u'2014, Kurt Griffiths'
copyright = u'2014, Kurt Griffiths and Rackspace Hosting'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Expand Down Expand Up @@ -189,7 +189,7 @@
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
html_show_copyright = False

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
Expand Down
2 changes: 2 additions & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Resources
---------

- `The Definitive Introduction to Falcon <https://speakerdeck.com/cabrera/the-definitive-introduction-to-falcon>`_
- `An Unladen Web Framework <http://blog.kgriffs.com/2013/07/02/python-fast-web-service-framework.html>`_.


User Guide
Expand All @@ -85,6 +86,7 @@ User Guide
user/install
user/quickstart
user/tutorial
user/faq


.. Community Guide
Expand Down
5 changes: 4 additions & 1 deletion doc/user/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
.. error responses for auth - 404 ?
.. error hooks
.. document all the individual error classes?
.. stacked hooks
.. stacked hooks
.. auth whitelist
.. processing file uploads from forms
.. static file serving
8 changes: 8 additions & 0 deletions doc/user/deployment.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. _deployment:

Deploying Your Web API
======================

[talk about, diagram async, host, etc.]

[async front, async to backend options - asyncio, gevent, etc.]
142 changes: 142 additions & 0 deletions doc/user/faq.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
.. _faq:

Questions & Answers
===================

Is Falcon thread-safe?
----

New Request and Response objects are created for each incoming HTTP request.
However, a single instance of each resource class attached to a route is
shared among all requests. Therefore, as long as you are careful about the
way responders access class member variables to avoid conflicts, your
WSGI app should be thread-safe.

That being said, Falcon-based services are usually deployed using green
threads (via the gevent library or similar) which aren't truly running
concurrently, so there may be some edge cases where Falcon is not
thread-safe that haven't been discovered yet.

*Caveat emptor!*

Why doesn't Falcon create a new Resource instance for every request?
----
Falcon generally tries to minimize the number of objects that it
instantiates. It does this for two reasons: first, to avoid the expense of
creating the object, and second to mitigate memory fragmentation.

Therefore, when adding a route, Falcon requires an *instance* of your
resource class, rather than the class type. That same instance will be used
to server all requests coming in on that route.

How can I pass data from a hook to a responders, and between hooks?
----
You can inject extra responder kwargs from a hook by adding them
to the *params* dict passed into the hook. You can also add custom data to
the req.env WSGI dict, as a way of passing contextual information around.

.. note::
Falcon 0.2 will add a dict to Request to provide a cleaner alternative to
using req.env.

Does Falcon set Content-Length or do I need to do that explicitly?
----

Falcon will try to do this for you, based on the value of `resp.body`,
`resp.data`, or `resp.stream_len` (whichever is set in the response, checked
in that order.)

For dynamically-generated content, you can choose to leave off `stream_len`,
in which case Falcon will then leave off the Content-Length header, and
hopefully your WSGI server will do the Right Thing™ (assuming you've told
it to enable keep-alive).

.. note:: PEP-333 prohibits apps from setting hop-by-hop headers itself,
such as Transfer-Encoding.

I'm setting a response body, but it isn't getting returned. What's going on?
----

Falcon skips processing the response body to save a few cycles when the HTTP
spec defines that the response should *have* no body. First, if the client
sends a HEAD request, the response body will be empty. Second, if the response
status set by a resource is one of the following, Falcon will skip processing
the response body::

falcon.HTTP_100
falcon.HTTP_204
falcon.HTTP_416
falcon.HTTP_304

Why does raising an error inside a resource crash my app?
----

Generally speaking, Falcon assumes that resource responders (such as *on_get*,
*on_post*, etc.) will, for the most part, do the right thing. In other words,
Falcon doesn't try very hard to protect responder code from itself.

This approach reduces the number of (often) extraneous checks that Falcon
would otherwise have to perform, making the framework more efficient. With
that in mind, writing a high-quality API based on Falcon requires that:

#. Resource responders set response variables to sane values.
#. Your code is well-tested, with high code coverage.
#. Errors are anticipated, detected, and handled appropriately within
each responder and with the aid of custom error handlers.

.. note:: Falcon will re-raise errors that do not inherit from
``falcon.HTTPError`` unless you have registered a custom error
handler for that type (see also: :ref:`falcon.API <api>`).

Why are trailing slashes trimmed from req.path?
----

Falcon normalizes incoming URI paths to simplify later processing and
improve the predictability of application logic. In addition to stripping
a trailing slashes, if any, Falcon will convert empty paths to '/'.

Note also that routing is also normalized, so adding a route for '/foo/bar'
also implicitly adds a route for '/foo/bar/'. Requests coming in for either
path will be sent to the same resource.

Why are field names in URI templates restricted to certain characters?
----

Field names are restricted to the ASCII characters a-z, A-Z, and '_'. Using a
restricted set of characters reduces the overhead of parsing incoming
requests.

Why is my query parameter missing from the req object?
----

If a query params does not have a value, Falcon will treat it as though the
param were omitted completely from the URI. For example, 'foo' or 'foo=' will
result in the parameter being ignored.

Is there a way for me to ensure headers are sent to clients in a specific order?
----

In order to generate HTTP responses as quickly as possible, Falcon does not
try to sort or even logically group related headers in the HTTP response.

.. note about stream being consumed for 'application/x-www-form-urlencoded’
.. If Falcon is designed for building web APIs, why does it support forms?
.. ----
.. Doesn't support files, allows same code to handle both...
.. What happens if an error is raised from a hook?
.. ----
.. Falcon will catch the error, and do one of three things:
.. 1. If the error is an instance of *HTTPError* (or a child of *HTTPError*), Falcon will convert it to an HTTP response and return that to the client.
.. 2. If there is a custom error handler, that will be called and given a chance to clean up resources and set up the Response object. When the handler returns, Falcon will immediately return a response to the client.
.. 3. If the type is unrecognized, it is re-raised and will be handled by your WSGI server.
.. Note that when an error is raised, it short-circuits the normal request chain.
.. Coming soon: before vs. after... work to catch HTTPError and other handlers, and set resp,
.. then continue with after hooks so can DRY up logic you want to run when an
.. error occurs. For example, serialize error to a normalized response body
.. scheme.
34 changes: 26 additions & 8 deletions doc/user/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -569,17 +569,35 @@ for information that will help them crack your API.
Error Handling
--------------
When something goes horribly (or mildly) wrong, you *could* manually set the
error status, appropriate response headers, and even an error body using the
``resp`` object. However, Falcon tries to make things a bit easier by
providing a set of exceptions you can raise when something goes wrong. In fact,
if Falcon catches any exception your responder throws that inherits from
``falcon.HTTPError``, the framework will convert that exception to an
appropriate HTTP error response.
Generally speaking, Falcon assumes that resource responders (*on_get*,
*on_post*, etc.) will, for the most part, do the right thing. In other words,
Falcon doesn't try very hard to protect responder code from itself.
This approach reduces the number of (often) extraneous checks that Falcon
would otherwise have to perform, making the framework more efficient. With
that in mind, writing a high-quality API based on Falcon requires that:
1. Resource responders set response variables to sane values.
1. Your code is well-tested, with high code coverage.
1. Errors are anticipated, detected, and handled appropriately within each
responder.
.. note::
Falcon will re-raise errors that do not inherit from ``falcon.HTTPError``
unless you have registered a custom error handler for that type
(see also: :ref:`falcon.API <api>`).
Speaking of error handling, when something goes horribly (or mildly) wrong,
you *could* manually set the error status, appropriate response headers, and
even an error body using the ``resp`` object. However, Falcon tries to make
things a bit easier by providing a set of exceptions you can raise when
something goes wrong. In fact, if Falcon catches any exception your responder
throws that inherits from ``falcon.HTTPError``, the framework will convert
that exception to an appropriate HTTP error response.
You may raise an instance of ``falcon.HTTPError``, or use any one
of a number of predefined error classes that try to do "the right thing" in
setting appropriate headers and bodies. Have a look at the docstrings for
setting appropriate headers and bodies. Have a look at the docs for
any of the following to get more information on how you can use them in your
API:
Expand Down
4 changes: 3 additions & 1 deletion falcon/api_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ def compile_uri_template(template):
Args:
template: A Level 1 URI template. Method responders must accept, as
arguments, all fields specified in the template (default '/').
arguments, all fields specified in the template (default '/').
Note that field names are restricted to ASCII a-z, A-Z, and
the underscore '_'.
Returns:
(template_field_names, template_regex)
Expand Down
15 changes: 14 additions & 1 deletion falcon/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,14 @@ class Request(object):
content_length (int): Value of the Content-Length header converted
to an int, or *None* if the header is missing.
stream: File-like object for reading the body of the request, if any.
any.
Note:
If an HTML form is POSTed to the API using the
*application/x-www-form-urlencoded* media type, Falcon
will consume `stream` in order to parse the parameters
and merge them into the query string parameters. In this
case, the stream will be left at EOF.
date (datetime): Value of the Date header, converted to a
`datetime.datetime` instance. The header value is assumed to
conform to RFC 1123.
Expand Down Expand Up @@ -463,6 +470,12 @@ def get_header(self, name, required=False):
def get_param(self, name, required=False, store=None):
"""Return the value of a query string parameter as a string.
Note:
If an HTML form is POSTed to the API using the
*application/x-www-form-urlencoded* media type, the
parameters from the request body will be merged into
the query string parameters.
Args:
name (str): Parameter name, case-sensitive (e.g., 'sort')
required (bool, optional): Set to True to raise HTTPBadRequest
Expand Down

0 comments on commit 49604c1

Please sign in to comment.