Update the complex example given in the quickstart and README so that it now works in light of a breaking change to the HTTPUnauthorized class. Note this breaking change in the changelog. Closes #757
22 KiB
1.0.0
Breaking Changes
The deprecated global hooks feature has been removed.
APIno longer acceptsbeforeandafterkwargs. 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
paramsargument. 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 anif resource is not Nonecheck 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 = TrueThe
HTTPUnauthorizedinitializer 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_encodedattribute 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') else: 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, andHTTPUnavailableForLegalReasonserror classes were added.The
HTTPStatusclass is now available directly under the falcon module, and has been properly documented.Support for HTTP redirections was added via a set of
HTTPStatussubclasses. 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 ofHTTPError.The default 404 responder now raises an instance of
HTTPErrorinstead 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 theResponseclass. Previously there was no way to check if a header had been set. The newget_header()method facilitates this and other use cases.Request.client_accepts_msgpacknow recognizes "application/msgpack", in addition to "application/x-msgpack".New
access_routeandremote_addrproperties were added to theRequestclass for getting upstream IP addresses.The
RequestandResponseclasses now support range units other than bytes.The
APIandStartResponseMockclass types can now be customized by inheriting from falcon.testing.TestBase and overriding theapi_classandsrmock_classclass 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_rangewas improved by ~50%.A new param,
obs_date, was added tofalcon.Request.get_header_as_datetime(), and defaults toFalse. This improves the method's performance when obsolete date formats do not need to be supported.
Fixed
- 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
Response.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_typeis now delayed until after all other properties of theRequestclass have been initialized, in case the context type's own initialization depends on any ofRequest's properties. - A case was fixed in which reading from
Request.streamcould hang when usingwsgirefto 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.
0.3.0
New
- This release includes a new router architecture for improved performance and flexibility.
- A custom router can now be specified when instantiating the :py
APIclass. - URI templates can now include multiple parameterized fields within a single path segment.
- Falcon now supports reading and writing cookies.
- Falcon now supports Jython 2.7.
- A method for getting a query param as a date was added to the
:py
Requestclass. - Date headers are now returned as :py
datetime.datetimeobjects. - A default value can now be specified when calling :py
Request.get_param. This provides an alternative to using the pattern:: value = req.get_param(name) or default_value - Friendly constants for status codes were added (e.g., :py
falcon.HTTP_NO_CONTENTvs. :pyfalcon.HTTP_204.) - Several minor performance optimizations were made to the code base.
Breaking Changes
- Date headers are now returned as :py
datetime.datetimeobjects instead of strings.
Fixed
- The query string parser was modified to improve handling of percent-encoded data.
- Several errors in the documentation were corrected.
- The :py
sixpackage was pinned to 1.4.0 or better. :pysix.PY2is required by Falcon, but that wasn't added to :pysixuntil version 1.4.0.
0.2.0
New
- Since 0.1 we've added proper RTD docs to make it easier for everyone to get started with the framework. Over time we will continue adding content, and we would love your help!
- Falcon now supports "wsgi.filewrapper". You can assign any file-like object to resp.stream and Falcon will use "wsgi.filewrapper" to more efficiently pipe the data to the WSGI server.
- Support was added for automatically parsing requests containing "application/x-www-form-urlencoded" content. Form fields are now folded into req.params.
- Custom Request and Response classes are now supported. You can specify custom types when instantiating falcon.API.
- A new middleware feature was added to the framework. Middleware deprecates global hooks, and we encourage everyone to migrate as soon as possible.
- A general-purpose dict attribute was added to Request. Middleware, hooks, and responders can now use req.context to share contextual information about the current request.
- A new method, append_header, was added to falcon.API to allow setting multiple values for the same header using comma separation. Note that this will not work for setting cookies, but we plan to address this in the next release (0.3).
- A new "resource" attribute was added to hooks. Old hooks that do not accept this new attribute are shimmed so that they will continue to function. While we have worked hard to minimize the performance impact, we recommend migrating to the new function signature to avoid any overhead.
- Error response bodies now support XML in addition to JSON. In addition, the HTTPError serialization code was refactored to make it easier to implement a custom error serializer.
- A new method, "set_error_serializer" was added to falcon.API. You can use this method to override Falcon's default HTTPError serializer if you need to support custom media types.
- Falcon's testing base class, testing.TestBase was improved to facilitate Py3k testing. Notably, TestBase.simulate_request now takes an additional "decode" kwarg that can be used to automatically decode byte-string PEP-3333 response bodies.
- An "add_link" method was added to the Response class. Apps can use this method to add one or more Link header values to a response.
- Added two new properties, req.host and req.subdomain, to make it easier to get at the hostname info in the request.
- Allow a wider variety of characters to be used in query string params.
- Internal APIs have been refactored to allow overriding the default routing mechanism. Further modularization is planned for the next release (0.3).
- Changed req.get_param so that it behaves the same whether a list was specified in the query string using the HTML form style (in which each element is listed in a separate 'key=val' field) or in the more compact API style (in which each element is comma-separated and assigned to a single param instance, as in 'key=val1,val2,val3')
- Added a convenience method, set_stream(...), to the Response class for setting the stream and its length at the same time, which should help people not forget to set both (and save a few keystrokes along the way).
- Added several new error classes, including HTTPRequestEntityTooLarge, HTTPInvalidParam, HTTPMissingParam, HTTPInvalidHeader and HTTPMissingHeader.
- Python 3.4 is now fully supported.
- Various minor performance improvements
Breaking Changes
- The deprecated util.misc.percent_escape and util.misc.percent_unescape functions were removed. Please use the functions in the util.uri module instead.
- The deprecated function, API.set_default_route, was removed. Please use sinks instead.
- HTTPRangeNotSatisfiable no longer accepts a media_type parameter.
- When using the comma-delimited list convention, req.get_param_as_list(...) will no longer insert placeholders, using the None type, for empty elements. For example, where previously the query string "foo=1,,3" would result in ['1', None, '3'], it will now result in ['1', '3'].
Fixed
- Ensure 100% test coverage and fix any bugs identified in the process.
- Fix not recognizing the "bytes=" prefix in Range headers.
- Make HTTPNotFound and HTTPMethodNotAllowed fully compliant, according to RFC 7231.
- Fixed the default on_options responder causing a Cython type error.
- URI template strings can now be of type unicode under Python 2.
- When SCRIPT_NAME is not present in the WSGI environ, return an empty string for the req.app property.
- Global "after" hooks will now be executed even when a responder raises an error.
- Fixed several minor issues regarding testing.create_environ(...)
- Work around a wsgiref quirk, where if no content-length header is submitted by the client, wsgiref will set the value of that header to an empty string in the WSGI environ.
- Resolved an issue causing several source files to not be Cythonized.
- Docstrings have been edited for clarity and correctness.
0.1.10
Fixed
- SCRIPT_NAME may not always be present in the WSGI environment, so treat it as an empty string if not present.
0.1.9
Fixed
- Addressed style issues reported by the latest pyflakes version
- Fixed body not being decoded from UTF-8 in HTTPError tests
- Remove unnecessary ordereddict requirement on Python 2.6
0.1.8
Breaking Changes
- srmock.headers have been normalized such that header names are always lowercase. This was done to make tests that rely on srmock less fragile.
- Falcon now sends response headers as all lower-case ala node.js. This will not break well-behaved clients, since HTTP specifies that header names are case-insensitive.
- The 'scheme' argument to HTTPUnauthorized can no longer be passed positionally; it must be a named argument.
- You can no longer overload a single resource class to respond to
multiple routes that differ by URI template params. This has come to be
viewed as an anti-pattern, and so it will no longer be supported. If you
attempt to have a single
OxResourcethat you try to overload to respond to both, e.g.,PUT /oxen/old-benandGET /oxen, it will no longer work. Developers should be advised to resist the temptation to overload their resources; instead, create multiple resources, i.e.,OxResourceandOxenResource. It is common to put these two classes in the same module.
Fixed
- srmock.headers_dict is now implemented using a case-insensitive dict
- Per RFC 3986, Falcon now decodes escaped characters in the query string, plus convert '+' -> ' '. Also, Falcon now decodes multi-byte UTF-8 sequences after they have been unescaped.
New
- Custom error handlers can be registered via a new API.add_error_handler method. You can use this to DRY your error handling logic by registering handlers that will get called whenever a given exception type is raised.
- Support for "request sinks" was added to falcon.API. If no route matches a request, but the path in the requested URI matches a given prefix, Falcon will pass control to the given sink, regardless of the HTTP method requested.
- uri module added to falcon.util which includes utilities for encoding and decoding URIs, as well as parsing a query string into a dict. This methods are more robust and more performant than their counterparts in urllib.
- Subsequent calls to req.uri are now faster since the property now clones a cached dict instead of building a new one from scratch each time.
- falcon.util now includes a case-insensitive dict borrowed from the Requests library. It isn't particularly fast, but is there in case you want to use it for anything.
- Misc. performance optimizations to offset the impact of supporting case-sensitive headers and rigorous URI encoding/decoding.
- Py33 performance improvements
0.1.7
Breaking Changes
- req.get_params_as_list now inserts None as a placeholder for missing elements, and returns None all by itself if the param is present in the query string, but has an empty string as its value. (kgriffs)
Fixed
- req.client_accepts does not handle media type ranges. (kgriffs)
- req.stream semantics must be special-cased based on WSGI server. (kgriffs)
New
- A default (catch-all) route can now be set, to provide a resource for handling requests that would otherwise result in a 404 status code being returned to the client. This feature is esp. useful when implementing reverse proxies with Falcon. See also falcon.API.set_default_route(). (lichray)
- OPTIONS method requests are now automatically handled based on the responders defined by the resources attached to the target route. (lichray)
- Responders can now use the req.headers property to obtain a copy of all headers received from the client. Useful for custom header parsing and/or request forwarding. (lichray)
- Query param names may now contain dots. (sorenh)
- Falcon no longer warns about Cython when installing under PyPy. (cabrera)
- A client's preferred media type can be determined via a new method, req.client_prefers(). (kgriffs)
- util.to_query_str now recognizes lists, and serializes them as a comma- delimited list, passing each element through str(). (kgriffs)
0.1.6.post3
Fixed
- Content-Length is now calculated correctly for Unicode bodies (flaper87)
- Status code 500 is now returned for type errors raised within responders, even when wrapped by several hooks.
0.1.6.post2
Fixed
- testtools is no longer a required dependency (cabrera)
New
- Add HTTPNotAcceptable for responding with HTTP status code 406 (lichray)
- Add HTTPLenghRequired for responding with HTTP status code 411 (cabrera)
- Add generic req.client_accepts() method (lichray)
0.1.6
Fixed
- Don't percent-escape common query chars!
0.1.5
Fixed
- Unicode characters in HTTPError body strings are now encoded properly to UTF-8.
- Unicode characters in resp.location and resp.content_location now are now percent-escaped.
- Tox environments no longer issue warnings/errors re incompatible cythoned files.
New
- req.get_param and friends now accepts an optional param, "store", that takes a dict-like object. The value for the specified param, if found, will be inserted into the store, i.e., store[param] = value. Useful for building up kwargs.
- req.get_param_as_bool now accepts capitalized booleans as well as 'yes' and 'no'.
- Extended "falcon-ext" benchmark added to falcon-bench for testing more taxing, wost-case requests.
- cProfile enabled for tests.
- cProfile option added to falcon-bench.
- Experimental memory profiling added to falcon-bench.
- py3kwarn env added to tox (run manually).
0.1.4
Fixed
- req.path now strips trailing slashes in keeping with the design decision in 0.1.2 to abstract those away from the app.
0.1.3
Fixed
- Moved property descriptions out of class docstrings into the property docstrings themselves so they show up in help().
- on_* responder methods in a resource class must define all URI template field names for any route attached to that resource. If they do not, Falcon will return "405 Method not allowed". This lets you add multiple routes to the same resource, in order to serve, for example, POST requests to "/super" and GET requests to "/super/{name}". In this example, a POST request to "/super/man" would result in a 405 response to the client, since the responder method does not define a "name" argument.
Breaking Changes
- req.date now returns a datetime instance, and raises HTTPBadRequest if the value of the Date header does not conform to RFC 1123.
- Query string parsing is now a little stricter regarding what kinds of field names it will accept. Generally, you will be safe if you stick with letters, numbers, dashes, and/or underscores.
- Header and query parsing is more strict now. Instead of returning None when a value cannot be parsed, Request will raise HTTPBadRequest.
New
- Added min and max arguments to req.get_param_as_int() to help with input validation.
- Added transform argument to req.get_param_as_list for supplying a converter function for list elements.
- Added req.get_param_as_bool() for automagically converting from "true" and "false" to True and False, respectively.
- Added the req.relative_uri property which will return app + path + query string.
- Added falcon.to_query_str() to provide an optimized query string generator that apps can use when generating href's.
- Improved performance when no query string is present in the request URI.
0.1.2
Fixed
- Falcon requires QUERY_STRING in WSGI environ, but PEP-333 does not require it
- Hook decorators can overwrite each other's actions
- Test coverage is not 100% when branch coverage is enabled
Breaking Changes
- Renamed falcon.testing.TestSuite to TestBase
- Renamed TestBase.prepare hook to TestBase.before
New
- Python 2.6 support
- Added TestBase.after hook
- Made testtools dependency optional (falls back to unittest if import fails)
- Trailing slashes in routes and request paths are ignored, so you no longer need to add two routes for each resource
0.1.1
Fixed
- Falcon won't install on a clean system
- Multiple headers possible in the HTTP response
- testing.create_environ not setting all PEP-3333 vars
- testing.StartRequestMock does not accept exc_info per PEP-3333
- Tests not at 100% code coverage
New
- Hooks: falcon.before and falcon.after decorators can apply hooks to entire resources and/or individual methods. Hooks may also be attached globally by passing them into the falcon.API initializer.
- Common request and response headers can now be accessed as attributes, e.g. "req.content_length" and "resp.etag".
- Cython: On installation, Falcon will now compile itself with Cython when available. This boosts the framework's performance by ~20%.
- PyPy and Python 3.3 support
- Vastly improved docstrings
0.1.0
Initial release.