Skip to content

Commit 0a02ea2

Browse files
authored
docs(FAQ): update FAQ to reflect new developments in Falcon 3.0 (#1782)
* docs(FAQ): update FAQ to reflect new developments in Falcon 3.0 * docs(FAQ): revise the WebSocket FAQ item * docs(install): add a note on ASGI server installation
1 parent 910b2fa commit 0a02ea2

File tree

2 files changed

+71
-58
lines changed

2 files changed

+71
-58
lines changed

docs/user/faq.rst

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,22 @@ when adding a route, Falcon requires an *instance* of your resource class,
3030
rather than the class type. That same instance will be used to serve all
3131
requests coming in on that route.
3232

33-
Why does raising an error inside a resource crash my app?
34-
---------------------------------------------------------
33+
What happens if my responder raises an error?
34+
---------------------------------------------
3535
Generally speaking, Falcon assumes that resource responders (such as
3636
``on_get()``, ``on_post()``, etc.) will, for the most part, do the right thing.
3737
In other words, Falcon doesn't try very hard to protect responder code from
3838
itself.
3939

40-
This approach reduces the number of checks that Falcon
41-
would otherwise have to perform, making the framework more efficient. With
42-
that in mind, writing a high-quality API based on Falcon requires that:
40+
.. note::
41+
As of version 3.0, the framework will no longer propagate uncaught
42+
exceptions to the application server.
43+
Instead, the default ``Exception`` handler will return an HTTP 500 response
44+
and log details of the exception to ``wsgi.errors``.
45+
46+
Although providing basic error handlers, Falcon optimizes for the most common
47+
case where resource responders do not raise any errors for valid requests.
48+
With that in mind, writing a high-quality API based on Falcon requires that:
4349

4450
#. Resource responders set response variables to sane values.
4551
#. Your code is well-tested, with high code coverage.
@@ -103,30 +109,41 @@ run into any issues, please let us know.
103109
Does Falcon support asyncio?
104110
------------------------------
105111

106-
Due to the limitations of WSGI, Falcon is unable to support ``asyncio`` at this
107-
time. However, we are exploring alternatives to WSGI (such
108-
as `ASGI <https://github.com/django/asgiref/blob/master/specs/asgi.rst>`_)
109-
that will allow us to support asyncio natively in the future.
112+
Starting with version 3.0, the `ASGI <https://asgi.readthedocs.io/en/latest/>`_
113+
flavor of Falcon now proudly supports :any:`asyncio`!
114+
Use the :class:`falcon.asgi.App` class to create an async application, and
115+
serve it via an :ref:`ASGI application server <install_asgi_server>` such as
116+
Uvicorn.
110117

111-
In the meantime, we recommend using the battle-tested
112-
`gevent <http://www.gevent.org/>`_ library via
113-
Gunicorn or uWSGI to scale IO-bound services.
118+
Alternatively, IO-bound WSGI applications can be scaled using the battle-tested
119+
`gevent <http://www.gevent.org/>`_ library via Gunicorn or uWSGI.
114120
`meinheld <https://pypi.org/project/meinheld/>`_ has also been used
115-
successfully by the community to power high-throughput, low-latency services.
116-
Note that if you use Gunicorn, you can combine gevent and PyPy to achieve an
117-
impressive level of performance. (Unfortunately, uWSGI does not yet support
118-
using gevent and PyPy together.)
121+
successfully by the community to power high-throughput, low-latency WSGI
122+
services.
123+
124+
.. tip::
125+
Note that if you use Gunicorn, you can combine gevent and PyPy to achieve
126+
an impressive level of performance.
127+
(Unfortunately, uWSGI does not yet support using gevent and PyPy together.)
119128

120129
Does Falcon support WebSocket?
121130
------------------------------
122131

123-
Due to the limitations of WSGI, Falcon is unable to support the WebSocket
124-
protocol as stated above.
132+
The async flavor of Falcon supports the
133+
`ASGI <https://asgi.readthedocs.io/en/latest/>`_ WebSocket protocol.
134+
See also: :ref:`ws`.
125135

126-
In the meantime, you might try leveraging
127-
`uWSGI's native WebSocket support <http://uwsgi.readthedocs.io/en/latest/WebSockets.html>`_,
128-
or implementing a standalone service via Aymeric Augustin's
129-
handy `websockets <https://pypi.python.org/pypi/websockets/4.0.1>`_ library.
136+
WSGI applications might try leveraging
137+
`uWSGI's native WebSocket support <http://uwsgi.readthedocs.io/en/latest/WebSockets.html>`_
138+
or `gevent-websocket's <https://pypi.org/project/gevent-websocket>`_
139+
``GeventWebSocketWorker`` for Gunicorn.
140+
141+
As an option, it may make sense to design WebSocket support as a separate
142+
service due to very different performance characteristics and interaction
143+
patterns, compared to a regular RESTful API. In addition to (obviously!)
144+
Falcon's native ASGI support, a standalone WebSocket service could also be
145+
implemented via Aymeric Augustin's handy
146+
`websockets <https://pypi.python.org/pypi/websockets>`_ library.
130147

131148
Routing
132149
~~~~~~~
@@ -137,43 +154,14 @@ How do I implement CORS with Falcon?
137154
In order for a website or SPA to access an API hosted under a different
138155
domain name, that API must implement
139156
`Cross-Origin Resource Sharing (CORS) <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`_.
140-
For a public API, implementing CORS in Falcon can be as simple as implementing
141-
a middleware component similar to the following:
157+
For a public API, implementing CORS in Falcon can be as simple as passing the
158+
``cors_enable`` flag (set to ``True``) when instantiating
159+
:ref:`your application <app>`.
142160

143-
.. code:: python
161+
Further CORS customization is possible via :class:`~falcon.CORSMiddleware`
162+
(for more information on managing CORS in Falcon, see also :ref:`cors`).
144163

145-
class CORSComponent:
146-
def process_response(self, req, resp, resource, req_succeeded):
147-
resp.set_header('Access-Control-Allow-Origin', '*')
148-
149-
if (req_succeeded
150-
and req.method == 'OPTIONS'
151-
and req.get_header('Access-Control-Request-Method')
152-
):
153-
# NOTE(kgriffs): This is a CORS preflight request. Patch the
154-
# response accordingly.
155-
156-
allow = resp.get_header('Allow')
157-
resp.delete_header('Allow')
158-
159-
allow_headers = req.get_header(
160-
'Access-Control-Request-Headers',
161-
default='*'
162-
)
163-
164-
resp.set_headers((
165-
('Access-Control-Allow-Methods', allow),
166-
('Access-Control-Allow-Headers', allow_headers),
167-
('Access-Control-Max-Age', '86400'), # 24 hours
168-
))
169-
170-
When using the above approach, OPTIONS requests must also be special-cased in
171-
any other middleware or hooks you use for auth, content-negotiation, etc. For
172-
example, you will typically skip auth for preflight requests because it is
173-
simply unnecessary; note that such request do not include the Authorization
174-
header in any case.
175-
176-
For more sophisticated use cases, have a look at Falcon add-ons from the
164+
For even more sophisticated use cases, have a look at Falcon add-ons from the
177165
community, such as `falcon-cors <https://github.com/lwcolton/falcon-cors>`_, or
178166
try one of the generic
179167
`WSGI CORS libraries available on PyPI <https://pypi.python.org/pypi?%3Aaction=search&term=cors&submit=search>`_.
@@ -723,7 +711,8 @@ How can I handle forward slashes within a route template field?
723711
In Falcon 1.3 we shipped initial support for
724712
`field converters <http://falcon.readthedocs.io/en/stable/api/routing.html#field-converters>`_.
725713
We’ve discussed building on this feature to support consuming multiple path
726-
segments ala Flask. This work is currently planned for 2.0.
714+
segments ala Flask. This work is currently planned to commence after the 3.0
715+
release.
727716

728717
In the meantime, the workaround is to percent-encode the forward slash. If you
729718
don’t control the clients and can't enforce this, you can implement a Falcon

docs/user/install.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ Waitress can be good alternative for Windows users if they want quick start usin
100100
101101
$ pip install [gunicorn|uwsgi|waitress]
102102
103+
.. _install_asgi_server:
104+
105+
ASGI Server
106+
-----------
107+
108+
Conversely, in order to run an ``async``
109+
:class:`Falcon ASGI app <falcon.asgi.App>`, you will need an
110+
`ASGI <https://asgi.readthedocs.io/en/latest/>`_ application server
111+
(Falcon only supports ASGI 3.0+, aka the single-callable application style).
112+
113+
Uvicorn is a popular choice, owing to its fast and stable
114+
implementation. What is more, Uvicorn is supported on Windows, and on PyPy
115+
(however, both at a performance loss compared to CPython on Unix-like systems).
116+
117+
Falcon is also regularly tested against Daphne, the current ASGI reference
118+
server.
119+
120+
For a more in-depth overview of available servers, see also:
121+
`ASGI Implementations <https://asgi.readthedocs.io/en/latest/implementations.html>`_.
122+
123+
.. code:: bash
124+
125+
$ pip install [uvicorn|daphne|hypercorn]
126+
103127
Source Code
104128
-----------
105129

0 commit comments

Comments
 (0)