Skip to main content

The Flask Request Object

The Request object in Flask is the primary interface for interacting with incoming HTTP data. Implemented in flask.wrappers.Request, it extends Werkzeug's base request handling to provide Flask-specific context, such as matched routing rules and blueprint information.

In practice, developers rarely instantiate this class directly. Instead, they interact with the flask.request proxy, which points to the Request instance associated with the current request context.

Accessing Incoming Data

The Request object provides several attributes to access data sent by the client, depending on the content type of the request.

Form Data

For standard HTML forms (typically POST or PUT requests), data is accessed via request.form. This is a multi-dictionary containing the key-value pairs from the form body.

As seen in the flaskr tutorial's authentication logic (examples/tutorial/flaskr/auth.py):

@bp.route("/login", methods=("GET", "POST"))
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
# ... logic to validate user ...

JSON Data

For APIs, the request.json attribute automatically parses the request body as JSON if the Content-Type header is set to application/json.

An example from the test suite (tests/test_testing.py) demonstrates this:

@app.post("/")
def index():
return f"Hello, {flask.request.json['name']}!"

If JSON parsing fails, the on_json_loading_failed method is triggered. In debug mode, this will re-raise the original BadRequest exception to provide a detailed traceback; otherwise, it returns a standard 400 error.

File Uploads

Files uploaded via a multipart/form-data form are available in request.files.

Flask includes a specific debug helper in _load_form_data to assist with common mistakes. If a developer attempts to access request.files but the form was submitted without the correct enctype, Flask will attach a specialized error message in debug mode via attach_enctype_error_multidict to explain that enctype="multipart/form-data" is required.

Routing and Context

After the Flask application matches a URL to a view function, the Request object is populated with metadata about the match.

  • url_rule: The werkzeug.routing.Rule instance that matched the request.
  • view_args: A dictionary of variables extracted from the URL (e.g., {'id': 5} for a route like /user/<int:id>).
  • endpoint: The internal name of the view function (e.g., auth.login).
  • blueprint: The name of the blueprint the request belongs to. This is derived from the endpoint by taking the part before the last dot.

The blueprints property (added in version 2.0.1) provides a list of all blueprint names from the current one up through any parent blueprints, which is useful for nested blueprint structures.

Request Limits and Configuration

Flask allows controlling the maximum size of incoming requests to prevent denial-of-service attacks or excessive memory usage. These limits are managed through properties on the Request class that fall back to application configuration.

Global Configuration

The following configuration keys in app.config define the default limits:

  • MAX_CONTENT_LENGTH: The maximum total bytes read.
  • MAX_FORM_MEMORY_SIZE: The maximum size for non-file form fields.
  • MAX_FORM_PARTS: The maximum number of fields in a multipart body.

Per-Request Overrides

A significant feature of the Request implementation in src/flask/wrappers.py is the ability to override these limits for specific requests or views.

def test_limit_config(app: Flask):
app.config["MAX_CONTENT_LENGTH"] = 100
r = Request({})
with app.app_context():
# Falls back to config
assert r.max_content_length == 100

# Override for this specific request
r.max_content_length = 90
assert r.max_content_length == 90

When these limits are exceeded, Flask raises a 413 RequestEntityTooLarge exception.

The Request Proxy

The flask.request object is actually a LocalProxy defined in src/flask/globals.py. It looks up the actual Request object in the current application context (_cv_app).

# src/flask/globals.py
request: RequestProxy = LocalProxy(
_cv_app, "request", unbound_message=_no_req_msg
)

This design allows the request object to be imported globally while always pointing to the data for the specific HTTP request being handled by the current thread or greenlet. Attempting to access request outside of an active request context will result in a RuntimeError with the message "Working outside of request context."