diff --git a/docs/user/faq.rst b/docs/user/faq.rst index 941689e59..992925afe 100644 --- a/docs/user/faq.rst +++ b/docs/user/faq.rst @@ -30,16 +30,22 @@ when adding a route, Falcon requires an *instance* of your resource class, rather than the class type. That same instance will be used to serve all requests coming in on that route. -Why does raising an error inside a resource crash my app? ---------------------------------------------------------- +What happens if my responder raises an error? +--------------------------------------------- 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 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: +.. note:: + As of version 3.0, the framework will no longer propagate uncaught + exceptions to the application server. + Instead, the default ``Exception`` handler will return an HTTP 500 response + and log details of the exception to ``wsgi.errors``. + +Although providing basic error handlers, Falcon optimizes for the most common +case where resource responders do not raise any errors for valid requests. +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. @@ -103,30 +109,41 @@ run into any issues, please let us know. Does Falcon support asyncio? ------------------------------ -Due to the limitations of WSGI, Falcon is unable to support ``asyncio`` at this -time. However, we are exploring alternatives to WSGI (such -as `ASGI `_) -that will allow us to support asyncio natively in the future. +Starting with version 3.0, the `ASGI `_ +flavor of Falcon now proudly supports :any:`asyncio`! +Use the :class:`falcon.asgi.App` class to create an async application, and +serve it via an :ref:`ASGI application server ` such as +Uvicorn. -In the meantime, we recommend using the battle-tested -`gevent `_ library via -Gunicorn or uWSGI to scale IO-bound services. +Alternatively, IO-bound WSGI applications can be scaled using the battle-tested +`gevent `_ library via Gunicorn or uWSGI. `meinheld `_ has also been used -successfully by the community to power high-throughput, low-latency services. -Note that if you use Gunicorn, you can combine gevent and PyPy to achieve an -impressive level of performance. (Unfortunately, uWSGI does not yet support -using gevent and PyPy together.) +successfully by the community to power high-throughput, low-latency WSGI +services. + +.. tip:: + Note that if you use Gunicorn, you can combine gevent and PyPy to achieve + an impressive level of performance. + (Unfortunately, uWSGI does not yet support using gevent and PyPy together.) Does Falcon support WebSocket? ------------------------------ -Due to the limitations of WSGI, Falcon is unable to support the WebSocket -protocol as stated above. +The async flavor of Falcon supports the +`ASGI `_ WebSocket protocol. +See also: :ref:`ws`. -In the meantime, you might try leveraging -`uWSGI's native WebSocket support `_, -or implementing a standalone service via Aymeric Augustin's -handy `websockets `_ library. +WSGI applications might try leveraging +`uWSGI's native WebSocket support `_ +or `gevent-websocket's `_ +``GeventWebSocketWorker`` for Gunicorn. + +As an option, it may make sense to design WebSocket support as a separate +service due to very different performance characteristics and interaction +patterns, compared to a regular RESTful API. In addition to (obviously!) +Falcon's native ASGI support, a standalone WebSocket service could also be +implemented via Aymeric Augustin's handy +`websockets `_ library. Routing ~~~~~~~ @@ -137,43 +154,14 @@ How do I implement CORS with Falcon? In order for a website or SPA to access an API hosted under a different domain name, that API must implement `Cross-Origin Resource Sharing (CORS) `_. -For a public API, implementing CORS in Falcon can be as simple as implementing -a middleware component similar to the following: +For a public API, implementing CORS in Falcon can be as simple as passing the +``cors_enable`` flag (set to ``True``) when instantiating +:ref:`your application `. -.. code:: python +Further CORS customization is possible via :class:`~falcon.CORSMiddleware` +(for more information on managing CORS in Falcon, see also :ref:`cors`). - class CORSComponent: - def process_response(self, req, resp, resource, req_succeeded): - resp.set_header('Access-Control-Allow-Origin', '*') - - if (req_succeeded - and req.method == 'OPTIONS' - and req.get_header('Access-Control-Request-Method') - ): - # NOTE(kgriffs): This is a CORS preflight request. Patch the - # response accordingly. - - allow = resp.get_header('Allow') - resp.delete_header('Allow') - - allow_headers = req.get_header( - 'Access-Control-Request-Headers', - default='*' - ) - - resp.set_headers(( - ('Access-Control-Allow-Methods', allow), - ('Access-Control-Allow-Headers', allow_headers), - ('Access-Control-Max-Age', '86400'), # 24 hours - )) - -When using the above approach, OPTIONS requests must also be special-cased in -any other middleware or hooks you use for auth, content-negotiation, etc. For -example, you will typically skip auth for preflight requests because it is -simply unnecessary; note that such request do not include the Authorization -header in any case. - -For more sophisticated use cases, have a look at Falcon add-ons from the +For even more sophisticated use cases, have a look at Falcon add-ons from the community, such as `falcon-cors `_, or try one of the generic `WSGI CORS libraries available on PyPI `_. @@ -723,7 +711,8 @@ How can I handle forward slashes within a route template field? In Falcon 1.3 we shipped initial support for `field converters `_. We’ve discussed building on this feature to support consuming multiple path -segments ala Flask. This work is currently planned for 2.0. +segments ala Flask. This work is currently planned to commence after the 3.0 +release. In the meantime, the workaround is to percent-encode the forward slash. If you don’t control the clients and can't enforce this, you can implement a Falcon diff --git a/docs/user/install.rst b/docs/user/install.rst index bdad07903..9cd751ad8 100644 --- a/docs/user/install.rst +++ b/docs/user/install.rst @@ -100,6 +100,30 @@ Waitress can be good alternative for Windows users if they want quick start usin $ pip install [gunicorn|uwsgi|waitress] +.. _install_asgi_server: + +ASGI Server +----------- + +Conversely, in order to run an ``async`` +:class:`Falcon ASGI app `, you will need an +`ASGI `_ application server +(Falcon only supports ASGI 3.0+, aka the single-callable application style). + +Uvicorn is a popular choice, owing to its fast and stable +implementation. What is more, Uvicorn is supported on Windows, and on PyPy +(however, both at a performance loss compared to CPython on Unix-like systems). + +Falcon is also regularly tested against Daphne, the current ASGI reference +server. + +For a more in-depth overview of available servers, see also: +`ASGI Implementations `_. + +.. code:: bash + + $ pip install [uvicorn|daphne|hypercorn] + Source Code -----------