Changelog for Falcon 4.1.0#
Summary#
This release contains enhancements to media handling, serving static files, and a fix for the WebSockets-sink interaction, alongside performance optimizations and full support for CPython 3.14.
During this release cycle, we have migrated to publishing to PyPI with a Trusted Publisher (thanks to @webknjaz for helping to iron out the workflow details).
For those relying on other package distribution channels than PyPI, we have prepared a brand new Packaging Guide for Falcon. Please check it out and let us know what you think! Additionally, we have formalized our security maintenance policy as well as the status of stable releases: Releases and Versioning.
This release also incorporates many pull requests submitted by our community. We would like to extend our heartfelt thanks to all 17 contributors who made this release possible!
Changes to Supported Platforms#
CPython 3.14 is now fully supported. (#2413)
Although the Falcon 4.x series is only guaranteed to support Python 3.10+, this release still supports 3.8 & 3.9 at runtime using the pure Python wheel.
Falcon 4.2 is expected to drop the end-of-life Python 3.8 completely (but runtime support will continue for 3.9 on a best effort basis).
New & Improved#
StaticRoutenow rendersEtagheaders. It also checksIf-None-Matchin requests and returns HTTP 304 response if appropriate. (#2243)StaticRoutenow sets theLast-Modifiedheader when serving static files. The improved implementation also checks the value of theIf-Modified-Sinceheader, and renders an HTTP 304 response when the requested file has not been modified. (#2244)Similar to
create_environ(), thecreate_scope()testing helper now preserves the raw URI path, and propagates it to the created ASGI connection scope as theraw_pathbyte string (according to the ASGI specification). (#2262)Two new media_type constants,
falcon.MEDIA_CSVandfalcon.MEDIA_PARQUET, were added in order to provide better support for Python data analysis applications out of the box. (#2335)Support for allowing cross-origin private network access was added to the built-in
CORSMiddleware. The new feature is off by default, and can be enabled by passing the keyword argumentallow_private_network=TruetoCORSMiddlewareduring initialization. (#2381)The
falcon.secure_filename()utility function can now ensure that the length of the sanitized filename does not exceed the requested limit (passed via themax_lengthargument). In addition, a new option,max_secure_filename_length, was added toMultipartParseOptionsin order to automatically populate this argument when referencing a body part’ssecure_filename. (#2420)The
unset_cookie()method now accepts asame_siteparameter (with underscore) for consistency withset_cookie(). The previoussamesiteparameter (without underscore) is now deprecated (referencing it will emit a deprecation warning). (#2453)A new method,
__rich__, has been added tofalcon.testing.Resultfor facilitating a rich-text representation when used together with the popular rich library.Provided you have installed both
falconandrichinto your environment, you should be able to see a prettier rendition of the below 404-result:>>> import falcon >>> import falcon.testing >>> import rich.pretty >>> rich.pretty.install() >>> client = falcon.testing.TestClient(falcon.App()) >>> client.get('/endpoint') Result<404 Not Found application/json b'{"title": "404 Not Found"}'>
(The actual appearance may depend on your terminal and/or REPL settings.) (#2457)
The cythonization process was revised in the light of the performance improvements in newer CPython versions (especially 3.12+), and the compilation is now largely confined to hand-crafted C/Cython code. As a result, the framework should run even faster on modern CPython. (#2470)
JSONHandlercan now detect a non-standard (not a subclass ofValueError) deserialization error type for a custom loads function.(Normally,
json.loads()and third party alternatives do raise a subclass ofValueErroron invalid input data, however, this is not the case for, e.g., the popular msgspec library at the time of writing.) (#2476)
Fixed#
Previously, Falcon’s WebSocket implementation was not documented to route the request to any
sink. However, in the case of a missing route, a matching sink was actually invoked, passingwsin place of the incompatibleresp.This mismatch has been addressed by introducing a ws keyword argument (similar to ASGI
error handlers) for sink functions meant to accept WebSocket connections.For backwards-compatibility, when ws is absent from the sink’s signature, the
WebSocketobject is still passed in place of the incompatible resp. This behavior will change in Falcon 5.0: when draining a WebSocket connection, resp will always be set toNone. (#2414)
Misc#
The readability of the Contributing docs was improved by properly rendering GitHub Markdown-flavored checkboxes. (#2318)
The
falcon.testing.httpnowcompatibility alias is now considered deprecated, and will be removed in Falcon 5.0. Use thefalcon.http_now()function instead. (#2389)
Contributors to this Release#
Many thanks to all of our talented and stylish contributors for this release!