Changelog for Falcon 2.0.0¶
Summary¶
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.
Changes to Supported Platforms¶
CPython 3.7 is now fully supported.
Falcon 2.x series is the last to support Python language version 2. As a result, support for CPython 2.7 and PyPy2.7 will be removed in Falcon 3.0.
Support for CPython 3.4 is now deprecated and will be removed in Falcon 3.0.
Support for CPython 2.6, CPython 3.3 and Jython 2.7 has been dropped.
Breaking Changes¶
Previously, several methods in the
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 offalcon.Response
now raise an instance ofValueError
if an attempt is made to use them for Set-Cookie:set_header()
,delete_header()
,get_header()
,set_headers()
.falcon.testing.Result.json
now returnsNone
when the response body is empty, rather than raising an error.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.get_param_as_bool()
no longer raises an error for a valueless parameter when theblank_as_true
keyword argument isFalse
. Instead,False
is simply returned in that case.keep_blank_qs_values
now defaults toTrue
instead ofFalse
.auto_parse_qs_csv
now defaults toFalse
instead ofTrue
.independent_middleware
kwarg onfalcon.API
now defaults toTrue
instead ofFalse
.The
stream_len
property of theResponse
class was changed to be an alias of the newcontent_length
property. Please useset_stream()
orcontent_length
instead, going forward, asstream_len
is now deprecated.Request
context_type
was changed from dict to a bare class implementing the mapping interface. (See also: How do I adapt my code to default context type changes in Falcon 2.0?)Response
context_type
was changed from dict to a bare class implementing the mapping interface. (See also: How do I adapt my code to default context type changes in Falcon 2.0?)JSONHandler
andHTTPError
no longer use ujson in lieu of the standard json library (when ujson is available in the environment). Instead,JSONHandler
can now be configured to use arbitrarydumps()
andloads()
functions. If you also need to customizeHTTPError
serialization, you can do so viaset_error_serializer()
.The
find()
method for a custom router is now required to accept thereq
keyword argument that was added in a previous release. The backwards-compatible shim was removed.All middleware methods and 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
set_error_serializer()
for the past few releases. The backwards-compatible shim has been removed.An internal function,
make_router_search()
, was removed from theapi_helpers
module.An internal function,
wrap_old_error_serializer()
, was removed from theapi_helpers
module.In order to improve performance, the
falcon.Request.headers
andfalcon.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
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,bounded_stream
may be used instead.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:
# Before def handle_error(ex, req, resp, params): pass # Falcon 2.0 def handle_error(req, resp, ex, params): pass
See also:
add_error_handler()
strip_url_path_trailing_slash
now defaults toFalse
instead ofTrue
.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 theRequest
class.The deprecated
get_param_as_dict()
method alias was removed from theRequest
class. Please useget_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.
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 themap_http_methods()
function directly from theiradd_route()
method if they require this mapping.The
serialize()
media handler method now receives an extra content_type argument, while thedeserialize()
method now takes stream, content_type, and content_length arguments, rather than a single raw argument. The raw data can still be obtained by executingraw = stream.read()
.See also:
BaseHandler
The deprecated
falcon.routing.create_http_method_map()
method was removed.The keyword arguments for
parse_query_string()
were renamed to be more concise:# Before parsed_values = parse_query_string( query_string, keep_blank_qs_values=True, parse_qs_csv=False ) # Falcon 2.0 parsed_values = parse_query_string( query_string, keep_blank=True, csv=False )
auto_parse_qs_csv
now defaults toFalse
instead ofTrue
.The
HTTPRequestEntityTooLarge
class was renamed toHTTPPayloadTooLarge
.Two of the keyword arguments for
get_param_as_int()
were renamed to avoid shadowing built-in Python names:# Before dpr = req.get_param_as_int('dpr', min=0, max=3) # Falcon 2.0 dpr = req.get_param_as_int('dpr', min_value=0, max_value=3)
The
falcon.media.validators.jsonschema.validate()
decorator now usesfunctools.wraps()
to make the decorated method look like the original.Previously,
HTTPError
instances for which the has_representation property evaluated toFalse
were not passed to custom error serializers (such as in the case of types that subclassNoRepresentation
). This has now been fixed so that custom error serializers will be called for all instances ofHTTPError
.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
if_match
andif_none_match
properties now return a list offalcon.ETag
objects rather than the raw value of the If-Match or If-None-Match headers, respectively.When setting the
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
falcon.DEFAULT_MEDIA_TYPE
andfalcon.MEDIA_JSON
constants, as well as the default value of the media_type keyword argument specified for thefalcon.API
initializer. This change also affects the default value of theRequestOptions.default_media_type
andResponseOptions.default_media_type
options.
New & Improved¶
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.
Removed the
six
andpython-mimeparse
dependencies.Added a new
complete
property to theResponse
class. This can be used to short-circuit request processing when the response has been pre-constructed.Request
context_type
now defaults to a bare class allowing to set attributes on the request context object:# Before req.context['role'] = 'trial' req.context['user'] = 'guest' # Falcon 2.0 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
context_type
to dict. (See also: How do I adapt my code to default context type changes in Falcon 2.0?)Response
context_type
now defaults to a bare class allowing to set attributes on the response context object:# Before resp.context['cache_strategy'] = 'lru' # Falcon 2.0 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
context_type
to dict. (See also: How do I adapt my code to default context type changes in Falcon 2.0?)JSONHandler
can now be configured to use arbitrarydumps()
andloads()
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,
get_cookie_values()
, to theRequest
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.
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:
add_route()
The
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:
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:
# Before def handle_error(ex, req, resp, params): pass # Falcon 2.0 def handle_error(req, resp, ex, params): pass
See also:
add_error_handler()
.All error classes now accept a headers keyword argument for customizing response headers.
A new method,
get_param_as_float()
, was added to theRequest
class.A new method,
has_param()
, was added to theRequest
class.A new property,
content_length
, was added to theResponse
class. Eitherset_stream()
orcontent_length
should be used going forward, asstream_len
is now deprecated.All
get_param_*()
methods of theRequest
class now accept a default argument.A new header property,
expires
, was added to theResponse
class.The
CompiledRouter
class now exposes amap_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 thedeserialize()
method now takes stream, content_type, and content_length arguments, rather than a single raw argument. The raw data can still be obtained by executingraw = stream.read()
.See also:
BaseHandler
The
get_header()
method now accepts a default keyword argument.The
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
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
decode()
method now accepts an unquote_plus keyword argument. The new argument defaults toFalse
to avoid a breaking change.The
if_match()
andif_none_match()
properties now return a list offalcon.ETag
objects rather than the raw value of the If-Match or If-None-Match headers, respectively.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
falcon.DEFAULT_MEDIA_TYPE
andfalcon.MEDIA_JSON
constants, as well as the default value of the media_type keyword argument specified for thefalcon.API
initializer. This change also affects the default value of theRequestOptions.default_media_type
andResponseOptions.default_media_type
options.
Fixed¶
Fixed a docs issue where with smaller browser viewports, the API documentation will start horizontal scrolling.
The color scheme for the docs was modified to fix issues with contrast and readability when printing the docs or generating PDFs.
The
simulate_request()
method now forces header values to str on Python 2 as required by PEP-3333.The
HTTPRequestEntityTooLarge
class was renamed toHTTPPayloadTooLarge
and the reason phrase was updated per RFC 7231.The
falcon.CaseInsensitiveDict
class now inherits fromcollections.abc.MutableMapping
under Python 3, instead ofcollections.MutableMapping
.The
\ufffd
character is now disallowed in requested static file paths.The
falcon.media.validators.jsonschema.validate()
decorator now usesfunctools.wraps()
to make the decorated method look like the original.The
falcon-print-routes
CLI tool no longer raises an unhandled error when Falcon is cythonized.The plus character (
'+'
) is no longer unquoted in the request path, but only in the query string.Previously,
HTTPError
instances for which the has_representation property evaluated toFalse
were not passed to custom error serializers (such as in the case of types that subclassNoRepresentation
). This has now been fixed so that custom error serializers will be called for all instances ofHTTPError
.When setting the
etag
header property, the value will now be wrapped with double-quotes (if not already present) to ensure compliance with RFC 7232.Fixed
TypeError
being raised when using Falcon’s testing framework to simulate a request to a generator-based WSGI app.
Contributors to this Release¶
Many thanks to all of our talented and stylish contributors for this release!
Bertrand Lemasle
Patrick Schneeweis