@@ -30,16 +30,22 @@ when adding a route, Falcon requires an *instance* of your resource class,
3030rather than the class type. That same instance will be used to serve all
3131requests 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+ ---------------------------------------------
3535Generally speaking, Falcon assumes that resource responders (such as
3636``on_get() ``, ``on_post() ``, etc.) will, for the most part, do the right thing.
3737In other words, Falcon doesn't try very hard to protect responder code from
3838itself.
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.
103109Does 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
120129Does 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
131148Routing
132149~~~~~~~
@@ -137,43 +154,14 @@ How do I implement CORS with Falcon?
137154In order for a website or SPA to access an API hosted under a different
138155domain 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
177165community, such as `falcon-cors <https://github.com/lwcolton/falcon-cors >`_, or
178166try 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?
723711In Falcon 1.3 we shipped initial support for
724712`field converters <http://falcon.readthedocs.io/en/stable/api/routing.html#field-converters >`_.
725713We’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
728717In the meantime, the workaround is to percent-encode the forward slash. If you
729718don’t control the clients and can't enforce this, you can implement a Falcon
0 commit comments