docs/changes/2.0.0.rst
.. falcon-release: 2019-04-26
Many thanks to all of our awesome contributors (listed down below) who made this release possible!
In 2.0 we added a number of new convenience methods and properties. We also made it a lot cleaner and less error-prone to assign multiple routes to the same resource class via suffixed responders.
Also noteworthy is the significant effort we invested in improving the accuracy, clarity, and breadth of the docs. We hope these changes will help make the framework easier to learn for newcomers.
Middleware methods can now short-circuit request processing, and we improved cookie and ETag handling. Plus, the testing framework received several improvements to make it easier to simulate certain types of requests.
As this is the first major release that we have had in quite a while, we have taken the opportunity to clean up many parts of the framework. Deprecated variables, methods, and classes have been removed, along with all backwards-compatibility shims for old method signatures. We also changed the defaults for a number of request options based on community feedback.
Please carefully review the list of breaking changes below to see what you may need to tweak in your app to make it compatible with this release.
Previously, several methods in the :class:~falcon.Response class
could be used to attempt to set raw cookie headers. However,
due to the Set-Cookie header values not being combinable
as a comma-delimited list, this resulted in an
incorrect response being constructed for the user agent in
the case that more than one cookie was being set. Therefore,
the following methods of falcon.Response now raise an
instance of ValueError if an attempt is made to use them
for Set-Cookie: :meth:~falcon.Response.set_header,
:meth:~falcon.Response.delete_header, :meth:~falcon.Response.get_header,
:meth:~falcon.Response.set_headers.
:attr:falcon.testing.Result.json now returns None when the response body is
empty, rather than raising an error.
:meth:~falcon.Request.get_param_as_bool now defaults to treating valueless
parameters as truthy, rather than falsy. None is still returned
by default when the parameter is altogether missing.
:meth:~falcon.Request.get_param_as_bool no longer raises an error for a
valueless parameter when the blank_as_true keyword argument is False.
Instead, False is simply returned in that case.
:attr:~falcon.RequestOptions.keep_blank_qs_values now defaults to True
instead of False.
:attr:~falcon.RequestOptions.auto_parse_qs_csv now defaults to False
instead of True.
independent_middleware kwarg on :class:falcon.API now defaults to
True instead of False.
The stream_len property of the :class:~falcon.Response class was changed to
be an alias of the new :attr:~falcon.Response.content_length property. Please
use :meth:~falcon.Response.set_stream or :attr:~falcon.Response.content_length
instead, going forward, as stream_len is now deprecated.
Request :attr:~falcon.Request.context_type was changed from dict to a bare class
implementing the mapping interface.
(See also: :ref:bare_class_context_type)
Response :attr:~falcon.Response.context_type was changed from dict to a bare class
implementing the mapping interface.
(See also: :ref:bare_class_context_type)
:class:~.media.JSONHandler and :class:~.HTTPError no longer use
ujson in lieu of the standard json library (when ujson is available in
the environment). Instead, :class:~.media.JSONHandler can now be configured
to use arbitrary dumps() and loads() functions. If you
also need to customize :class:~.HTTPError serialization, you can do so via
:meth:~.API.set_error_serializer.
The find() method for a custom router is now required to accept the
req keyword argument that was added in a previous release. The
backwards-compatible shim was removed.
All :ref:middleware <middleware> methods and :ref:hooks <hooks> must
now accept the arguments as specified in the relevant interface definitions
as of Falcon 2.0. All backwards-compatible shims have been removed.
Custom error serializers are now required to accept the arguments as
specified by :meth:~.API.set_error_serializer for the past few releases.
The backwards-compatible shim has been removed.
An internal function, make_router_search(), was removed from the
api_helpers module.
An internal function, wrap_old_error_serializer(), was removed from the
api_helpers module.
In order to improve performance, the :attr:falcon.Request.headers and
:attr:falcon.Request.cookies properties now return a direct reference to
an internal cached object, rather than making a copy each time. This
should normally not cause any problems with existing apps since these objects
are generally treated as read-only by the caller.
The :attr:falcon.Request.stream attribute is no longer wrapped in a bounded
stream when Falcon detects that it is running on the wsgiref server. If you
need to normalize stream semantics between wsgiref and a production WSGI
server, :attr:~falcon.Request.bounded_stream may be used instead.
:attr:falcon.Request.cookies now gives precedence to the first value
encountered in the Cookie header for a given cookie name, rather than the
last.
The ordering of the parameters passed to custom error handlers was adjusted to be more intuitive and consistent with the rest of the framework::
def handle_error(ex, req, resp, params): pass
def handle_error(req, resp, ex, params): pass
See also: :meth:~.API.add_error_handler
:attr:~.falcon.RequestOptions.strip_url_path_trailing_slash now defaults
to False instead of True.
The deprecated falcon.testing.TestCase.api property was removed.
The deprecated falcon.testing.TestCase.api_class class variable was removed.
The deprecated falcon.testing.TestBase class was removed.
The deprecated falcon.testing.TestResource class was removed.
The deprecated protocol property was removed from the
:class:~falcon.Request class.
The deprecated get_param_as_dict() method alias was removed from the
:class:~falcon.Request class. Please use :meth:~falcon.Request.get_param_as_json
instead.
Routers were previously allowed to accept additional args and keyword arguments, and were not required to use the variadic form. Now, they are only allowed to accept additional options as variadic keyword arguments, and to ignore any arguments they don't support. This helps overridden router logic be less fragile in terms of their interface contracts, which also makes it easier to keep Falcon backwards-compatible in the face of any future changes in this area.
:meth:~.API.add_route previously accepted *args, but now no longer does.
The add_route() method for custom routers no longer takes a method_map
argument. Custom routers should, instead, call the
:meth:~falcon.routing.map_http_methods function directly
from their add_route() method if they require this mapping.
The serialize() media handler method now receives an extra
content_type argument, while the deserialize() method now takes
stream, content_type, and content_length arguments, rather than a
single raw argument. The raw data can still be obtained by executing
raw = stream.read().
See also: :class:~.media.BaseHandler
The deprecated falcon.routing.create_http_method_map() method was
removed.
The keyword arguments for :meth:~falcon.uri.parse_query_string were renamed
to be more concise::
parsed_values = parse_query_string( query_string, keep_blank_qs_values=True, parse_qs_csv=False )
parsed_values = parse_query_string( query_string, keep_blank=True, csv=False )
:attr:~.falcon.RequestOptions.auto_parse_qs_csv now defaults
to False instead of True.
The HTTPRequestEntityTooLarge class was renamed to
:class:~falcon.HTTPPayloadTooLarge.
Two of the keyword arguments for :meth:~falcon.Request.get_param_as_int were
renamed to avoid shadowing built-in Python names::
dpr = req.get_param_as_int('dpr', min=0, max=3)
dpr = req.get_param_as_int('dpr', min_value=0, max_value=3)
The :meth:falcon.media.validators.jsonschema.validate decorator now uses
:meth:functools.wraps to make the decorated method look like the original.
Previously, :class:~.HTTPError instances for which the has_representation
property evaluated to False were not passed to custom error serializers
(such as in the case of types that subclass
:class:~.NoRepresentation). This has now been fixed so
that custom error serializers will be called for all instances of
:class:~.HTTPError.
Request cookie parsing no longer uses the standard library for most of the parsing logic. This may lead to subtly different results for archaic cookie header formats, since the new implementation is based on RFC 6265.
The :attr:~falcon.Request.if_match and :attr:~falcon.Request.if_none_match properties
now return a list of :class:falcon.ETag objects rather than the raw
value of the If-Match or If-None-Match headers, respectively.
When setting the :attr:~falcon.Response.etag header property, the value will
now be wrapped with double-quotes (if not already present) to ensure
compliance with RFC 7232.
The default error serializer no longer sets the charset parameter for the
media type returned in the Content-Type header, since UTF-8 is the default
encoding for both JSON and XML media types. This should not break
well-behaved clients, but could impact test cases in apps that
assert on the exact value of the Content-Type header.
Similar to the change made to the default error serializer, the default JSON
media type generally used for successful responses was also modified
to no longer specify the charset parameter.
This change affects both the :data:falcon.DEFAULT_MEDIA_TYPE and
:data:falcon.MEDIA_JSON :ref:constants <media_type_constants>, as well
as the default value of the media_type keyword argument specified for
the :class:falcon.API initializer. This change also affects the default
value of the :attr:.RequestOptions.default_media_type and
:attr:.ResponseOptions.default_media_type options.
Several performance optimizations were made to hot code paths in the framework to make Falcon 2.0 even faster than 1.4 in some cases.
Numerous changes were made to the docs to improve clarity and to provide better recommendations on how to best use various parts of the framework.
Added a new :attr:~falcon.Response.headers property to the :class:~falcon.Response class.
Removed the :mod:six and :mod:python-mimeparse dependencies.
Added a new :attr:~falcon.Response.complete property to the :class:~falcon.Response
class. This can be used to short-circuit request processing when the response
has been pre-constructed.
Request :attr:~falcon.Request.context_type now defaults to a bare class allowing
to set attributes on the request context object::
req.context['role'] = 'trial' req.context['user'] = 'guest'
req.context.role = 'trial' req.context.user = 'guest'
To ease the migration path, the previous behavior is supported by implementing the mapping interface in a way that object attributes and mapping items are linked, and setting one sets the other as well. However, as of Falcon 2.0, the dict context interface is considered deprecated, and may be removed in a future release.
Applications can work around this change by explicitly overriding
:attr:~falcon.Request.context_type to dict.
(See also: :ref:bare_class_context_type)
Response :attr:~falcon.Response.context_type now defaults to a bare class allowing
to set attributes on the response context object::
resp.context['cache_strategy'] = 'lru'
resp.context.cache_strategy = 'lru'
To ease the migration path, the previous behavior is supported by implementing the mapping interface in a way that object attributes and mapping items are linked, and setting one sets the other as well. However, as of Falcon 2.0, the dict context interface is considered deprecated, and may be removed in a future release.
Applications can work around this change by explicitly overriding
:attr:~falcon.Response.context_type to dict.
(See also: :ref:bare_class_context_type)
:class:~.media.JSONHandler can now be configured to use arbitrary
dumps() and loads() functions. This enables support not only for
using any of a number of third-party JSON libraries, but also for
customizing the keyword arguments used when (de)serializing objects.
Added a new method, :meth:~falcon.Request.get_cookie_values, to the
:class:~falcon.Request class. The new method supports getting all values
provided for a given cookie, and is now the preferred mechanism for
reading request cookies.
Optimized request cookie parsing. It is now roughly an order of magnitude faster.
:meth:~falcon.Response.append_header now supports appending raw Set-Cookie header values.
Multiple routes can now be added for the same resource instance using a suffix to distinguish the set of responders that should be used. In this way, multiple closely-related routes can be mapped to the same resource while preserving readability and consistency.
See also: :meth:~.API.add_route
The :meth:falcon.media.validators.jsonschema.validate decorator now
supports both request and response validation.
A static route can now be configured to return the data from a default file when the requested file path is not found.
See also: :meth:~.API.add_static_route
The ordering of the parameters passed to custom error handlers was adjusted to be more intuitive and consistent with the rest of the framework::
def handle_error(ex, req, resp, params): pass
def handle_error(req, resp, ex, params): pass
See also: :meth:~.API.add_error_handler.
All error classes now accept a headers keyword argument for customizing
response headers.
A new method, :meth:~falcon.Request.get_param_as_float, was added to the
:class:~falcon.Request class.
A new method, :meth:~falcon.Request.has_param, was added to the
:class:~falcon.Request class.
A new property, :attr:~falcon.Response.content_length, was added to the
:class:~falcon.Response class. Either :meth:~falcon.Response.set_stream or
:attr:~falcon.Response.content_length should be used going forward, as
stream_len is now deprecated.
All get_param_*() methods of the :class:~falcon.Request class now accept a
default argument.
A new header property, :attr:~falcon.Response.expires, was added to the
:class:~falcon.Response class.
The :class:~.routing.CompiledRouter class now exposes a
:class:~falcon.routing.CompiledRouter.map_http_methods method that child
classes can override in order to customize the mapping of HTTP methods to
resource class methods.
The serialize() media handler method now receives an extra
content_type argument, while the deserialize() method now takes
stream, content_type, and content_length arguments, rather than a
single raw argument. The raw data can still be obtained by executing
raw = stream.read().
See also: :class:~.media.BaseHandler
The :meth:~falcon.Response.get_header method now accepts a default keyword
argument.
The :meth:~falcon.testing.TestClient.simulate_request method now supports
overriding the host and remote IP address in the WSGI environment, as well
as setting arbitrary additional CGI variables in the WSGI environment.
The :meth:~falcon.testing.TestClient.simulate_request method now supports
passing a query string as part of the path, as an alternative to using the
params or query_string keyword arguments.
Added a deployment guide to the docs for uWSGI and NGINX on Linux.
The :meth:~.uri.decode method now accepts an unquote_plus keyword
argument. The new argument defaults to False to avoid a breaking change.
The :meth:~falcon.Request.if_match and :meth:~falcon.Request.if_none_match properties
now return a list of :class:falcon.ETag objects rather than the raw
value of the If-Match or If-None-Match headers, respectively.
:meth:~.API.add_error_handler now supports specifying an iterable of
exception types to match.
The default error serializer no longer sets the charset parameter for the
media type returned in the Content-Type header, since UTF-8 is the default
encoding for both JSON and XML media types.
Similar to the change made to the default error serializer, the default JSON
media type generally used for successful responses was also modified
to no longer specify the charset parameter.
This change affects both the :data:falcon.DEFAULT_MEDIA_TYPE and
:data:falcon.MEDIA_JSON :ref:constants <media_type_constants>, as well
as the default value of the media_type keyword argument specified for
the :class:falcon.API initializer. This change also affects the default
value of the :attr:.RequestOptions.default_media_type and
:attr:.ResponseOptions.default_media_type options.
~falcon.testing.TestClient.simulate_request method now forces
header values to str on Python 2 as required by PEP-3333.HTTPRequestEntityTooLarge class was renamed to
:class:~falcon.HTTPPayloadTooLarge and the reason phrase was updated
per RFC 7231.falcon.CaseInsensitiveDict class now inherits from
:class:collections.abc.MutableMapping under Python 3, instead of
:class:collections.MutableMapping.\ufffd character is now disallowed in requested static file paths.falcon.media.validators.jsonschema.validate decorator now uses
:meth:functools.wraps to make the decorated method look like the original.falcon-print-routes CLI tool no longer raises an unhandled error
when Falcon is cythonized.'+') is no longer unquoted in the request path, but
only in the query string.~.HTTPError instances for which the has_representation
property evaluated to False were not passed to custom error serializers
(such as in the case of types that subclass
:class:~.NoRepresentation). This has now been fixed so
that custom error serializers will be called for all instances of
:class:~.HTTPError.~falcon.Response.etag header property, the value will
now be wrapped with double-quotes (if not already present) to ensure
compliance with RFC 7232.TypeError being raised when using Falcon's testing framework
to simulate a request to a generator-based WSGI app.Many thanks to all of our talented and stylish contributors for this release!
CaselIT <https://github.com/CaselIT>_DmitriiTrofimov <https://github.com/DmitriiTrofimov>_KingAkeem <https://github.com/KingAkeem>_Nateyo <https://github.com/Nateyo>_TheMushrr00m <https://github.com/TheMushrr00m>_ZDBioHazard <https://github.com/ZDBioHazard>_alysivji <https://github.com/alysivji>_aparkerlue <https://github.com/aparkerlue>_astonm <https://github.com/astonm>_awbush <https://github.com/awbush>_bendemaree <https://github.com/bendemaree>_bkcsfi <https://github.com/bkcsfi>_brooksryba <https://github.com/brooksryba>_carlodri <https://github.com/carlodri>_grktsh <https://github.com/grktsh>_hugovk <https://github.com/hugovk>_jmvrbanac <https://github.com/jmvrbanac>_kandziu <https://github.com/kandziu>_kgriffs <https://github.com/kgriffs>_klardotsh <https://github.com/klardotsh>_mikeylight <https://github.com/mikeylight>_mumrau <https://github.com/mumrau>_nZac <https://github.com/nZac>_navyad <https://github.com/navyad>_ozzzik <https://github.com/ozzzik>_paneru-rajan <https://github.com/paneru-rajan>_safaozturk93 <https://github.com/safaozturk93>_santeyio <https://github.com/santeyio>_sbensoussan <https://github.com/sbensoussan>_selfvin <https://github.com/selfvin>_snobu <https://github.com/snobu>_steven-upside <https://github.com/steven-upside>_tribals <https://github.com/tribals>_vytas7 <https://github.com/vytas7>_