Changelog for Falcon 1.0.0

Breaking Changes

  • The deprecated global hooks feature has been removed. API no longer accepts before and after kwargs. Applications can work around this by migrating any logic contained in global hooks to reside in middleware components instead.

  • The middleware method process_resource() must now accept an additional params argument. This gives the middleware method an opportunity to interact with the values for any fields defined in a route’s URI template.

  • The middleware method process_resource() is now skipped when no route is found for the incoming request. This avoids having to include an if resource is not None check when implementing this method. A sink may be used instead to execute logic in the case that no route is found.

  • An option was added to toggle automatic parsing of form params. Falcon will no longer automatically parse, by default, requests that have the content type “application/x-www-form-urlencoded”. This was done to avoid unintended side-effects that may arise from consuming the request stream. It also makes it more straightforward for applications to customize and extend the handling of form submissions. Applications that require this functionality must re-enable it explicitly, by setting a new request option that was added for that purpose, per the example below:

    app = falcon.API()
    app.req_options.auto_parse_form_urlencoded = True
  • The HTTPUnauthorized initializer now requires an additional argument, challenges. Per RFC 7235, a server returning a 401 must include a WWW-Authenticate header field containing at least one challenge.

  • The performance of composing the response body was improved. As part of this work, the Response.body_encoded attribute was removed. This property was only intended to be used by the framework itself, but any dependent code can be migrated per the example below:

    # Before
    body = resp.body_encoded
    # After
    if resp.body:
        body = resp.body.encode('utf-8')
        body = b''

New & Improved

  • A code of conduct was added to solidify our community’s commitment to sustaining a welcoming, respectful culture.

  • CPython 3.5 is now fully supported.

  • The constants HTTP_422, HTTP_428, HTTP_429, HTTP_431, HTTP_451, and HTTP_511 were added.

  • The HTTPUnprocessableEntity, HTTPTooManyRequests, and HTTPUnavailableForLegalReasons error classes were added.

  • The HTTPStatus class is now available directly under the falcon module, and has been properly documented.

  • Support for HTTP redirections was added via a set of HTTPStatus subclasses. This should avoid the problem of hooks and responder methods possibly overriding the redirect. Raising an instance of one of these new redirection classes will short-circuit request processing, similar to raising an instance of HTTPError.

  • The default 404 responder now raises an instance of HTTPError instead of manipulating the response object directly. This makes it possible to customize the response body using a custom error handler or serializer.

  • A new method, get_header(), was added to Response. Previously there was no way to check if a header had been set. The new get_header() method facilitates this and other use cases.

  • falcon.Request.client_accepts_msgpack() now recognizes “application/msgpack”, in addition to “application/x-msgpack”.

  • New access_route and remote_addr properties were added to Request for getting upstream IP addresses.

  • Request and Response now support range units other than bytes.

  • The API and StartResponseMock class types can now be customized by inheriting from TestBase and overriding the api_class and srmock_class class attributes.

  • Path segments with multiple field expressions may now be defined at the same level as path segments having only a single field expression. For example:

    api.add_route('/files/{file_id}', resource_1)
    api.add_route('/files/{file_id}.{ext}', resource_2)
  • Support was added to API.add_route() for passing through additional args and kwargs to custom routers.

  • Digits and the underscore character are now allowed in the falcon.routing.compile_uri_template() helper, for use in custom router implementations.

  • A new testing framework was added that should be more intuitive to use than the old one. Several of Falcon’s own tests were ported to use the new framework (the remainder to be ported in a subsequent release.) The new testing framework performs wsgiref validation on all requests.

  • The performance of setting Response.content_range was improved by ~50%.

  • A new param, obs_date, was added to falcon.Request.get_header_as_datetime(), and defaults to False. This improves the method’s performance when obsolete date formats do not need to be supported.


  • Field expressions at a given level in the routing tree no longer mask alternative branches. When a single segment in a requested path can match more than one node at that branch in the routing tree, and the first branch taken happens to be the wrong one (i.e., the subsequent nodes do not match, but they would have under a different branch), the other branches that could result in a successful resolution of the requested path will now be subsequently tried, whereas previously the framework would behave as if no route could be found.
  • The user agent is now instructed to expire the cookie when it is cleared via unset_cookie().
  • Support was added for hooks that have been defined via functools.partial().
  • Tunneled UTF-8 characters in the request path are now properly decoded, and a placeholder character is substituted for any invalid code points.
  • The instantiation of Request.context_type is now delayed until after all other properties of the Request class have been initialized, in case the context type’s own initialization depends on any of Request’s properties.
  • A case was fixed in which reading from could hang when using wsgiref to host the app.
  • The default error serializer now sets the Vary header in responses. Implementing this required passing the Response object to the serializer, which would normally be a breaking change. However, the framework was modified to detect old-style error serializers and wrap them with a shim to make them compatible with the new interface.
  • A query string containing malformed percent-encoding no longer causes the framework to raise an error.
  • Additional tests were added for a few lines of code that were previously not covered, due to deficiencies in code coverage reporting that have since been corrected.
  • The Cython note is no longer displayed when installing under Jython.
  • Several errors and ambiguities in the documentation were corrected.