diff --git a/docs/api/cors.rst b/docs/api/cors.rst index c731db897..40bec453a 100644 --- a/docs/api/cors.rst +++ b/docs/api/cors.rst @@ -7,10 +7,9 @@ CORS (CORS) is an additional security check performed by modern browsers to prevent unauthorized requests between different domains. -When implementing -a web API, it is common to have to also implement a CORS policy. Therefore, -Falcon provides an easy way to enable a simple CORS policy via a flag passed -to :class:`falcon.App` or :class:`falcon.asgi.App`. +When developing a web API, it is common to also implement a CORS +policy. Therefore, Falcon provides an easy way to enable a simple CORS policy +via a flag passed to :class:`falcon.App` or :class:`falcon.asgi.App`. By default, Falcon's built-in CORS support is disabled, so that any cross-origin requests will be blocked by the browser. Passing ``cors_enable=True`` will @@ -60,6 +59,11 @@ Usage app = falcon.asgi.App(middleware=falcon.CORSMiddleware( allow_origins='example.com', allow_credentials='*')) +.. note:: + Passing the ``cors_enable`` parameter set to ``True`` should be seen as + mutually exclusive with directly passing an instance of + :class:`~falcon.CORSMiddleware` to the application's initializer. + CORSMiddleware -------------- diff --git a/docs/api/routing.rst b/docs/api/routing.rst index 42f37469e..17256e02d 100644 --- a/docs/api/routing.rst +++ b/docs/api/routing.rst @@ -281,6 +281,9 @@ specifications in the URI template: some_resource ) +(See also how :class:`~.UUIDConverter` is used in Falcon's ASGI tutorial: +:ref:`asgi_tutorial_image_resources`.) + .. _routing_builtin_converters: Built-in Converters diff --git a/docs/api/websocket.rst b/docs/api/websocket.rst index 24b63e905..226c35123 100644 --- a/docs/api/websocket.rst +++ b/docs/api/websocket.rst @@ -17,7 +17,7 @@ ASGI application and a web browser, mobile app, or other client application. .. note:: See also :attr:`falcon.asgi.Response.sse` to learn more about Falcon's - Server-Sent Event (SSE) support, + Server-Sent Event (SSE) support. Usage ----- diff --git a/docs/user/faq.rst b/docs/user/faq.rst index 6f8fdd8c6..2c60e42a3 100644 --- a/docs/user/faq.rst +++ b/docs/user/faq.rst @@ -401,8 +401,8 @@ How can I pass data from a hook to a responder, 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 set custom attributes -on the ``req.context`` object, as a way of passing contextual information -around: +on the :attr:`req.context ` object, as a way of passing +contextual information around: .. code:: python @@ -439,7 +439,7 @@ plain HTTP 500 error. To provide your own 500 logic, you can add a custom error handler for Python's base :class:`Exception` type. This will not affect the default handlers for :class:`~.HTTPError` and :class:`~.HTTPStatus`. -See :ref:`errors` and the :meth:`falcon.API.add_error_handler` docs for more +See :ref:`errors` and the :meth:`falcon.App.add_error_handler` docs for more details. Request Handling @@ -449,7 +449,8 @@ How do I authenticate requests? ------------------------------- Hooks and middleware components can be used together to authenticate and authorize requests. For example, a middleware component could be used to -parse incoming credentials and place the results in ``req.context``. +parse incoming credentials and place the results in +:attr:`req.context `. Downstream components or hooks could then use this information to authorize the request, taking into account the user's role and the requested resource. @@ -558,8 +559,7 @@ installed by default, thus making the POSTed form available as POSTed form parameters may also be read directly from :attr:`~falcon.Request.stream` and parsed via -:meth:`falcon.uri.parse_query_string` or -`urllib.parse.parse_qs() `_. +:meth:`falcon.uri.parse_query_string` or :func:`urllib.parse.parse_qs`. .. _access_multipart_files: @@ -663,7 +663,7 @@ below: } - app = falcon.API() + app = falcon.App() app.add_route('/locations', LocationResource()) In the example above, ``LocationResource`` expects a query string containing @@ -768,38 +768,41 @@ types: Response Handling ~~~~~~~~~~~~~~~~~ -When would I use media, data, and stream? ------------------------------------------ +When would I use media, data, text, and stream? +----------------------------------------------- -These three parameters are mutually exclusive, you should only set one when +These four attributes are mutually exclusive, you should only set one when defining your response. -:ref:`resp.media ` is used when you want to use the Falcon serialization -mechanism. Just assign data to the attribute and falcon will take care of the -rest. +:attr:`resp.media ` is used when you want to use the +Falcon serialization mechanism. Just assign data to the attribute and Falcon +will take care of the rest. .. code:: python class MyResource: def on_get(self, req, resp): - resp.media = { 'hello': 'World' } + resp.media = {'hello': 'World'} -`resp.text` and `resp.data` are very similar, they both allow you to set the -body of the response. The difference being, `text` takes a string and `data` +:attr:`resp.text ` and +:attr:`resp.data ` are very similar, they both allow you +to set the body of the response. The difference being, +:attr:`~falcon.Response.text` takes a string, and :attr:`~falcon.Response.data` takes bytes. .. code:: python class MyResource: def on_get(self, req, resp): - resp.text = json.dumps({ 'hello': 'World' }) + resp.text = json.dumps({'hello': 'World'}) def on_post(self, req, resp): - resp.data = b'{ "hello": "World" }' - + resp.data = b'{"hello": "World"}' -`resp.stream` allows you to set a file-like object which returns bytes. We will -call `read()` until the object is consumed. +:attr:`resp.stream ` allows you to set a generator that +yields bytes, or a file-like object with a ``read()`` method that returns +bytes. In the case of a file-like object, the framework will call ``read()`` +until the stream is exhausted. .. code:: python @@ -807,23 +810,40 @@ call `read()` until the object is consumed. def on_get(self, req, resp): resp.stream = open('myfile.json', mode='rb') +See also the :ref:`outputting_csv_recipe` recipe for an example of using +:attr:`resp.stream ` with a generator. How can I use resp.media with types like datetime? -------------------------------------------------- -The default JSON handler for ``resp.media`` only supports the objects and types -listed in the table documented under -`json.JSONEncoder `_. -To handle additional types, you can either serialize them beforehand, or create -a custom JSON media handler that sets the `default` param for ``json.dumps()``. -When deserializing an incoming request body, you may also wish to implement -`object_hook` for ``json.loads()``. Note, however, that setting the `default` or -`object_hook` params can negatively impact the performance of (de)serialization. +The default JSON handler for :attr:`resp.media ` only +supports the objects and types listed in the table documented under +:any:`json.JSONEncoder`. + +To handle additional types in JSON, you can either serialize them beforehand, +or create a custom JSON media handler that sets the `default` param for +:func:`json.dumps`. When deserializing an incoming request body, you may also +wish to implement `object_hook` for :func:`json.loads`. Note, however, that +setting the `default` or `object_hook` params can negatively impact the +performance of (de)serialization. + +If you use an alternative JSON library, you might also look whether it provides +support for additional data types. For instance, the popular ``orjson`` opts to +automatically serialize :mod:`dataclasses`, :mod:`enums `, +:class:`~datetime.datetime` objects, etc. + +Furthermore, different Internet media types such as YAML, +:class:`msgpack `, etc might support more data +types than JSON, either as part of the respective (de)serialization format, or +via custom type extensions. 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.text`` or -``resp.data`` (whichever is set in the response, checked in that order.) +Falcon will try to do this for you, based on the value of +:attr:`resp.text `, +:attr:`resp.data ` or +:attr:`resp.media ` (whichever is set in the response, +checked in that order). For dynamically-generated content, you can choose to not set :attr:`~falcon.Response.content_length`, in which case Falcon will then leave @@ -987,7 +1007,7 @@ When it comes to app configuration, Falcon is not opinionated. You are free to choose from any of the excellent general-purpose configuration libraries maintained by the Python community. It’s pretty much up to you if you want to use the standard library or something like ``aumbry`` as demonstrated by this -`falcon example app `_ +`Falcon example app `_. (See also the **Configuration** section of our `Complementary Packages wiki page `_. diff --git a/docs/user/intro.rst b/docs/user/intro.rst index d5d1fd37c..05411b2c2 100644 --- a/docs/user/intro.rst +++ b/docs/user/intro.rst @@ -69,7 +69,7 @@ take care to keep logic paths within the framework simple, shallow and understandable. All of this makes it easier to reason about the code and to debug edge cases in large-scale deployments. -**Flexible.** Falcon leaves a lot of decisions and i`mplementation +**Flexible.** Falcon leaves a lot of decisions and implementation details to you, the API developer. This gives you a lot of freedom to customize and tune your implementation. Due to Falcon's minimalist design, Python community members are free to independently innovate on diff --git a/docs/user/tutorial-asgi.rst b/docs/user/tutorial-asgi.rst index 5c95ddadb..239e0c658 100644 --- a/docs/user/tutorial-asgi.rst +++ b/docs/user/tutorial-asgi.rst @@ -255,6 +255,8 @@ processing. to be picklable (which also implies that the task must be reachable from the global namespace, i.e., an anonymous ``lambda`` simply won't work). +.. _asgi_tutorial_image_resources: + Images Resource(s) ------------------ diff --git a/examples/things.py b/examples/things.py index e3efb78e4..7a9947300 100644 --- a/examples/things.py +++ b/examples/things.py @@ -22,7 +22,7 @@ def on_get(self, req, resp): ) -# falcon.API instances are callable WSGI apps +# falcon.App instances are callable WSGI apps # in larger applications the app is created in a separate file app = falcon.App()