Falcon allows for easy and customizable internet media type handling. By default Falcon only enables a single JSON handler. However, additional handlers can be configured through the falcon.RequestOptions
and falcon.ResponseOptions
objects specified on your falcon.API
.
Note
To avoid unnecessary overhead, Falcon will only process request media the first time the media property is referenced. Once it has been referenced, it’ll use the cached result for subsequent interactions.
Zero configuration is needed if you’re creating a JSON API. Just access or set the media
attribute as appropriate and let Falcon do the heavy lifting for you.
import falcon class EchoResource(object): def on_post(self, req, resp): message = req.media.get('message') resp.media = {'message': message} resp.status = falcon.HTTP_200
Warning
Once media
is called on a request, it’ll consume the request’s stream.
Falcon currently only provides a JSON Schema media validator; however, JSON Schema is very versatile and can be used to validate any deserialized media type that JSON also supports (i.e. dicts, lists, etc).
falcon.media.validators.jsonschema.validate(req_schema=None, resp_schema=None)
[source]
Decorator for validating req.media
using JSON Schema.
This decorator provides standard JSON Schema validation via the jsonschema
package available from PyPI. Semantic validation via the format keyword is enabled for the default checkers implemented by jsonschema.FormatChecker
.
Note
The jsonschema`
package must be installed separately in order to use this decorator, as Falcon does not install it by default.
See json-schema.org for more information on defining a compatible dictionary.
Parameters: |
---|
from falcon.media.validators import jsonschema # -- snip -- @jsonschema.validate(my_post_schema) def on_post(self, req, resp): # -- snip --
If JSON Schema does not meet your needs, a custom validator may be implemented in a similar manner to the one above.
Falcon currently only supports partial negotiation out of the box. By default, when the media
attribute is used it attempts to de/serialize based on the Content-Type
header value. The missing link that Falcon doesn’t provide is the connection between the falcon.Request
Accept
header provided by a user and the falcon.Response
Content-Type
header.
If you do need full negotiation, it is very easy to bridge the gap using middleware. Here is an example of how this can be done:
class NegotiationMiddleware(object): def process_request(self, req, resp): resp.content_type = req.accept
When creating your API object you can either add or completely replace all of the handlers. For example, lets say you want to write an API that sends and receives MessagePack. We can easily do this by telling our Falcon API that we want a default media-type of application/msgpack
and then create a new Handlers
object specifying the desired media type and a handler that can process that data.
import falcon from falcon import media handlers = media.Handlers({ 'application/msgpack': media.MessagePackHandler(), }) api = falcon.API(media_type='application/msgpack') api.req_options.media_handlers = handlers api.resp_options.media_handlers = handlers
Alternatively, if you would like to add an additional handler such as MessagePack, this can be easily done in the following manner:
import falcon from falcon import media extra_handlers = { 'application/msgpack': media.MessagePackHandler(), } api = falcon.API() api.req_options.media_handlers.update(extra_handlers) api.resp_options.media_handlers.update(extra_handlers)
class falcon.media.JSONHandler(dumps=None, loads=None)
[source]
JSON media handler.
This handler uses Python’s standard json
library by default, but can be easily configured to use any of a number of third-party JSON libraries, depending on your needs. For example, you can often realize a significant performance boost under CPython by using an alternative library. Good options in this respect include orjson
, python-rapidjson
, and mujson
.
Note
If you are deploying to PyPy, we recommend sticking with the standard library’s JSON implementation, since it will be faster in most cases as compared to a third-party library.
Overriding the default JSON implementation is simply a matter of specifying the desired dumps
and loads
functions:
import falcon from falcon import media import rapidjson json_handler = media.JSONHandler( dumps=rapidjson.dumps, loads=rapidjson.loads, ) extra_handlers = { 'application/json': json_handler, } api = falcon.API() api.req_options.media_handlers.update(extra_handlers) api.resp_options.media_handlers.update(extra_handlers)
By default, ensure_ascii
is passed to the json.dumps
function. If you override the dumps
function, you will need to explicitly set ensure_ascii
to False
in order to enable the serialization of Unicode characters to UTF-8. This is easily done by using functools.partial
to apply the desired keyword argument. In fact, you can use this same technique to customize any option supported by the dumps
and loads
functions:
from functools import partial from falcon import media import rapidjson json_handler = media.JSONHandler( dumps=partial( rapidjson.dumps, ensure_ascii=False, sort_keys=True ), )
Keyword Arguments: | |
---|---|
|
deserialize(stream, content_type, content_length)
[source]
Deserialize the falcon.Request
body.
Parameters: | |
---|---|
Returns: |
A deserialized object. |
Return type: |
serialize(media, content_type)
[source]
Serialize the media object on a falcon.Response
Parameters: | |
---|---|
Returns: |
The resulting serialized bytes from the input object. |
Return type: |
class falcon.media.MessagePackHandler
[source]
Handler built using the msgpack
module.
This handler uses msgpack.unpackb()
and msgpack.packb()
. The MessagePack bin
type is used to distinguish between Unicode strings (str
on Python 3, unicode
on Python 2) and byte strings (bytes
on Python 2/3, or str
on Python 2).
Note
This handler requires the extra msgpack
package (version 0.5.2 or higher), which must be installed in addition to falcon
from PyPI:
$ pip install msgpack
deserialize(stream, content_type, content_length)
[source]
Deserialize the falcon.Request
body.
Parameters: | |
---|---|
Returns: |
A deserialized object. |
Return type: |
serialize(media, content_type)
[source]
Serialize the media object on a falcon.Response
Parameters: | |
---|---|
Returns: |
The resulting serialized bytes from the input object. |
Return type: |
If Falcon doesn’t have an internet media type handler that supports your use case, you can easily implement your own using the abstract base class provided by Falcon:
class falcon.media.BaseHandler
[source]
Abstract Base Class for an internet media type handler
serialize(media, content_type)
[source]
Serialize the media object on a falcon.Response
Parameters: | |
---|---|
Returns: |
The resulting serialized bytes from the input object. |
Return type: |
deserialize(stream, content_type, content_length)
[source]
Deserialize the falcon.Request
body.
Parameters: | |
---|---|
Returns: |
A deserialized object. |
Return type: |
class falcon.media.Handlers(initial=None)
[source]
A dictionary like object that manages internet media type handlers.
The falcon
module provides a number of constants for common media types, including the following:
falcon.MEDIA_JSON falcon.MEDIA_MSGPACK falcon.MEDIA_YAML falcon.MEDIA_XML falcon.MEDIA_HTML falcon.MEDIA_JS falcon.MEDIA_TEXT falcon.MEDIA_JPEG falcon.MEDIA_PNG falcon.MEDIA_GIF
© 2019 by Falcon contributors
Licensed under the Apache License, Version 2.0.
https://falcon.readthedocs.io/en/2.0.0/api/media.html