Request: offer a way to validate `get_media()` as part of decoding the stream data to Python
- Dominant language
- Python
- Stars
- 9.8k
- Forks
- 1k
- Avg merge
- 5d 13h
- Merged PRs (30d)
- 7
Description
Currently there is no clean way (using standard internal Falcon methods) to validate and decode incoming data within the Request stream in a single step. This can matter because libraries such as [Pydantic v2](https://docs.pydantic.dev/latest/) and [msgspec](https://jcristharif.com/msgspec/) include native validation at the time of deserialization/decoding which generally outperforms converting from JSON to a Python dict and then reading the dict into an object (with validation). Pydantic v2, in particular, does not offer any way that I know of to convert from a JSON string into a dict in any performant way (it always assumes you are converting into a Pydantic schema).
Arguably, the best way to go about this currently is to use custom middleware that does an end-run around `get_media()` completely. For instance:
```python
import msgspec
class ValidatedMedia:
def process_resource(self, req, resp, resource, params):
# Fetch the expected msgspec struct somehow; here we assume it is a class property named like `PatchSchema`
schema_class = getattr(resource, f'{req.method.title()}Schema', None)
req.context.validated_media = msgspec.json.decode(req.stream.read(), type=schema_class)
```
It would be nice if there were some natively-supported method for doing this, though, without needing to police the project to make sure all views use `req.context.validated_media` (in this example) instead of the more standard `req.get_media()`. Unfortunately, it is not currently possible to achieve this with a custom Handler class alone, because the handler only receives the stream contents, content type, and content length from `get_media()`.
I don't have any specific suggestions for how this could best be implemented in Falcon. When I was originally looking through the Falcon source with an eye towards making this work, I considered allowing `get_media()` to pass arbitrary keyword-arguments through to the handler (which would allow something like `req.get_media(type=schema_class)` within the view logic itself to pass a msgspec schema straight through to a custom Handler class). However, this introduces indeterminate return types for `get_media()` based on whatever the custom Handler may be doing, which arguably is even less desirable than needing to rely on a Middleware-defined property.
Contributor guide
Research direction
Start by reading Falcon's Request.get_media() implementation and the custom Handler path described in the issue, then compare it with the middleware workaround using msgspec.json.decode. Define how native validation and decoding should be exposed without requiring views to use a separate context property, and ensure the resulting get_media() behavior and return type are clearly specified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100