Managing Request Payload Limits
When a user uploads a 2GB file to a route designed only for small profile pictures, it can exhaust server resources or disk space. Flask allows you to restrict the size and complexity of incoming request payloads globally or on a per-view basis to prevent such resource exhaustion.
Configuring Global Payload Limits
You can set application-wide limits using Flask's configuration dictionary. These limits apply to every request handled by the application unless specifically overridden.
from flask import Flask
app = Flask(__name__)
# Limit the total request body size to 16 Megabytes
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024 * 1024
# Limit the size of individual non-file form fields (default: 500,000 bytes)
app.config["MAX_FORM_MEMORY_SIZE"] = 100_000
# Limit the total number of fields in a multipart form (default: 1,000)
app.config["MAX_FORM_PARTS"] = 50
The MAX_CONTENT_LENGTH setting is the most common way to restrict file upload sizes. If a request exceeds this limit, Flask will raise a 413 Request Entity Too Large error when the request data is accessed.
Overriding Limits for Specific Views
In Flask 3.1 and later, you can override payload limits for specific requests. This is useful when you want a strict global limit but need to allow larger uploads on a specific administration or ingestion route.
You can modify these limits within a @app.before_request handler or at the beginning of a view function before accessing request.form or request.files.
from flask import request, abort
@app.post("/upload-large-video")
def upload_video():
# Increase the limit for this specific request to 500MB
request.max_content_length = 500 * 1024 * 1024
# Accessing request.files triggers the limit check
if "video" not in request.files:
return "No video part", 400
video = request.files["video"]
video.save(f"/var/uploads/{video.filename}")
return "Upload successful"
Handling Limit Violations
When a limit is exceeded, Flask raises a werkzeug.exceptions.RequestEntityTooLarge exception, which results in a HTTP 413 status code. You can provide a custom response for this error using an error handler.
from flask import render_template
@app.errorhandler(413)
def request_entity_too_large(error):
return "The file you uploaded is too large. Max size is 16MB.", 413
Multipart Form Constraints
Flask provides specific controls for multipart/form-data requests (typically used for file uploads) to protect against "hash collision" or "many-part" denial of service attacks.
Field Size Limits
MAX_FORM_MEMORY_SIZE (or request.max_form_memory_size) controls the maximum size of any non-file field. If a text field in a multipart form exceeds this size, a 413 error is raised.
Field Count Limits
MAX_FORM_PARTS (or request.max_form_parts) limits the total number of parts (fields and files) allowed in a single multipart request. This prevents attackers from sending thousands of small form fields to consume CPU cycles during parsing.
Important Considerations
- Enforcement Timing: Limits are enforced when the request data is first parsed. This usually happens when you access
request.form,request.files,request.get_json(), orrequest.data. - Missing Content-Length: If
MAX_CONTENT_LENGTHis set toNone(the default) and a request arrives without aContent-Lengthheader, Flask may refuse to read the data to avoid potential infinite streams, unless the WSGI server indicates the stream is terminated. - Server-Level Limits: While Flask enforces these limits at the application level, production web servers like Nginx or Apache often have their own limits (e.g.,
client_max_body_sizein Nginx). Ensure your server configuration matches or exceeds your Flask configuration.