Allow max content length to be modified on a per-request basis
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 3.7k
- Forks
- 206
- PR merge metrics
- No merged PRs in 30d
Description
The Request class, in src/quart/wrappers/request.py, has a max_content_length property which is writable: calling code can set it to None, which should remove any limit on the size of the request body. But the Body class checks expected_content_length against max_content_length in its __init__ function, and the value of max_content_length there is always the global default from app.config, because the body object is constructed before application code has a chance to set a different limit on the request. This means that if clients provide Content-Length headers on their uploads, the only way for the application to allow large uploads is by setting app.config["MAX_CONTENT_LENGTH"] = None for the entire application, rather than just for the route that expects the large uploads.
(Strictly speaking it's not the only way, since the application could also do request.body._must_raise = None before reading from the request body within a handler method, but that's a brittle workaround at best. Applications shouldn't have to touch private fields like that.)
Instead, the size should be checked only when the application starts to actually consume the request body, so that the application has a chance to modify max_content_length before doing that. An application should be able to implement a route like this:
@app.route("/upload", methods = ["PUT"])
async def handle_file_upload():
request.max_content_length = None
async for chunk in request.body:
...
…and have this route allow uploads of unlimited size, while other routes are still subject to the limit from app.config["MAX_CONTENT_LENGTH"].
However, this depends on fixing #152, so that Quart doesn't actually start reading the request body until the application starts to consume it. Currently, Quart begins reading the body into memory immediately, so the size limit has to be enforced immediately. There are size checks in both Body.__init__ and Body.append, both of which can run before the application starts to consume the body. The changes for #152 would involve removing the Body.append method and changing Body.__anext__ and Body.__await__ to read directly from the client instead of returning already-buffered input, so the size checks could be done in those places instead.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read src/quart/wrappers/request.py and the Body implementation, focusing on Body.init, Body.append, Body.anext, and Body.await. Review the dependency in #152 first to understand when request data is consumed. Done means a handler can set request.max_content_length before consuming request.body, while other routes retain app.config["MAX_CONTENT_LENGTH"].
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100