Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pallets/flask/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Flask provides Request and Response objects that wrap Werkzeug’s WSGI request and response handling with Flask-specific enhancements.

Request Object

The request object is a global proxy that provides access to incoming request data.

Accessing Request Data

from flask import Flask, request

app = Flask(__name__)

@app.route('/search')
def search():
    # Query parameters
    query = request.args.get('q', '')
    page = request.args.get('page', 1, type=int)
    
    # Form data (POST)
    username = request.form.get('username')
    
    # JSON data
    data = request.get_json()
    
    # Headers
    user_agent = request.headers.get('User-Agent')
    
    # Cookies
    session_id = request.cookies.get('session_id')
    
    return jsonify({'query': query, 'page': page})

Request Properties

From wrappers.py:18-54, the Flask Request class provides:
# URL information
request.url           # Full URL
request.base_url      # URL without query string
request.url_root      # Root URL
request.path          # Path portion
request.query_string  # Raw query string (bytes)

# Method and routing
request.method        # HTTP method (GET, POST, etc.)
request.endpoint      # Matched endpoint name
request.view_args     # URL parameter dict
request.url_rule      # Matched Rule object

# Client information
request.remote_addr   # Client IP address
request.user_agent    # User agent string
request.referrer      # Referring URL

Request Data Sources

Query String

Access GET parameters:
# URL: /search?q=flask&category=web
@app.route('/search')
def search():
    query = request.args.get('q')        # 'flask'
    category = request.args.get('category')  # 'web'
    
    # Get with default
    page = request.args.get('page', 1, type=int)
    
    # Get list of values
    tags = request.args.getlist('tag')
    
    return jsonify(request.args.to_dict())

Form Data

Access POST form data:
@app.route('/login', methods=['POST'])
def login():
    username = request.form['username']  # KeyError if missing
    password = request.form.get('password')  # None if missing
    
    # Check if key exists
    if 'remember_me' in request.form:
        # Set remember cookie
        pass
    
    return redirect('/dashboard')

JSON Data

Parse JSON request bodies:
@app.route('/api/users', methods=['POST'])
def create_user():
    # Automatically parses JSON
    data = request.get_json()
    
    # Force parsing even without Content-Type
    data = request.get_json(force=True)
    
    # Silent mode (returns None on error)
    data = request.get_json(silent=True)
    
    if data:
        name = data.get('name')
        email = data.get('email')
        return jsonify({'id': 123, 'name': name}), 201
    
    return jsonify({'error': 'Invalid JSON'}), 400

File Uploads

Handle uploaded files:
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return 'No file part', 400
    
    file = request.files['file']
    
    if file.filename == '':
        return 'No selected file', 400
    
    if file:
        filename = secure_filename(file.filename)
        file.save(f'/uploads/{filename}')
        return 'File uploaded', 201

Raw Data

Access raw request body:
@app.route('/webhook', methods=['POST'])
def webhook():
    # Raw bytes
    raw_data = request.data
    
    # As text
    text_data = request.get_data(as_text=True)
    
    # Stream for large files
    stream = request.stream
    
    return 'OK'

Request Limits

From wrappers.py:60-144, Flask provides security limits:
# Application-level defaults
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16 MB
app.config['MAX_FORM_MEMORY_SIZE'] = 500_000  # 500 KB
app.config['MAX_FORM_PARTS'] = 1_000

# Per-request override
@app.route('/upload', methods=['POST'])
def upload():
    request.max_content_length = 50 * 1024 * 1024  # 50 MB for this route
    # ... handle upload

Blueprint Context

From wrappers.py:162-195, access blueprint information:
@app.route('/admin/users')
def admin_users():
    # Current blueprint name
    blueprint = request.blueprint  # 'admin'
    
    # All blueprint names in hierarchy
    blueprints = request.blueprints  # ['admin']
    
    # Endpoint includes blueprint
    endpoint = request.endpoint  # 'admin.users'

Response Object

The Response object represents the HTTP response sent to the client.

Creating Responses

Simple Responses

from flask import Flask, Response

app = Flask(__name__)

@app.route('/')
def index():
    # String response (converted to Response)
    return 'Hello, World!'

@app.route('/json')
def json_response():
    # Dict/list (converted to JSON)
    return {'message': 'Hello', 'status': 'success'}

@app.route('/custom')
def custom():
    # Explicit Response object
    return Response('Custom response', mimetype='text/plain')

Response Tuples

Return status code and headers:
@app.route('/created')
def created():
    # (body, status)
    return 'Resource created', 201

@app.route('/with-headers')
def with_headers():
    # (body, status, headers)
    return 'OK', 200, {'X-Custom': 'value'}

@app.route('/json-created')
def json_created():
    # (body, headers) - status inferred
    return {'id': 123}, {'Location': '/api/resource/123'}

Response Properties

From wrappers.py:222-258:
@app.route('/example')
def example():
    response = Response('Hello')
    
    # Status
    response.status_code = 200
    response.status = '200 OK'
    
    # Headers
    response.headers['X-Custom'] = 'value'
    response.headers['Content-Type'] = 'application/json'
    
    # Cookies
    response.set_cookie('session', 'abc123')
    
    # MIME type
    response.mimetype = 'text/html'  # Default for Flask
    
    return response

Setting Cookies

Manage cookies in responses:
@app.route('/login', methods=['POST'])
def login():
    response = make_response(redirect('/dashboard'))
    
    # Simple cookie
    response.set_cookie('username', 'john')
    
    # With options
    response.set_cookie(
        'session_id',
        'abc123',
        max_age=3600,           # 1 hour
        secure=True,            # HTTPS only
        httponly=True,          # No JavaScript access
        samesite='Lax'          # CSRF protection
    )
    
    return response

@app.route('/logout')
def logout():
    response = make_response(redirect('/'))
    response.delete_cookie('session_id')
    return response

make_response()

Convert return values to Response objects (from app.py:1224-1273):
from flask import make_response

@app.route('/custom')
def custom():
    # String to Response
    response = make_response('Hello')
    response.headers['X-Custom'] = 'value'
    return response

@app.route('/render')
def render():
    # Template to Response
    html = render_template('page.html')
    response = make_response(html)
    response.headers['X-Page'] = 'home'
    return response

JSON Responses

Flask provides convenient JSON handling:
from flask import jsonify

@app.route('/api/user/<int:id>')
def get_user(id):
    user = {'id': id, 'name': 'John', 'email': 'john@example.com'}
    
    # jsonify() sets Content-Type to application/json
    return jsonify(user)

@app.route('/api/users')
def list_users():
    users = [{'id': 1, 'name': 'John'}, {'id': 2, 'name': 'Jane'}]
    return jsonify(users)

@app.route('/api/error')
def error():
    return jsonify({'error': 'Not found'}), 404

Streaming Responses

Stream large responses:
from flask import stream_with_context

@app.route('/large-file')
def large_file():
    def generate():
        with open('large_file.txt') as f:
            for line in f:
                yield line
    
    return Response(generate(), mimetype='text/plain')

@app.route('/events')
def events():
    def generate():
        for i in range(10):
            yield f'data: {i}\n\n'
            time.sleep(1)
    
    return Response(generate(), mimetype='text/event-stream')

File Downloads

Send files to clients:
from flask import send_file, send_from_directory

@app.route('/download/<filename>')
def download(filename):
    return send_from_directory('files', filename, as_attachment=True)

@app.route('/report')
def report():
    # Send file-like object
    buffer = BytesIO()
    buffer.write(b'Report content')
    buffer.seek(0)
    
    return send_file(
        buffer,
        mimetype='application/pdf',
        as_attachment=True,
        download_name='report.pdf'
    )

Request Context

The request object is context-local, available only during request handling:
from flask import request, has_request_context

def get_user_ip():
    if has_request_context():
        return request.remote_addr
    return None

@app.route('/')
def index():
    ip = get_user_ip()  # Works here
    return f'Your IP: {ip}'

# Outside request context
ip = get_user_ip()  # Returns None

Modifying Responses

After Request Handlers

Modify all responses:
@app.after_request
def add_header(response):
    response.headers['X-Custom-Header'] = 'value'
    response.headers['Cache-Control'] = 'no-store'
    return response

Per-Request Modifications

Modify specific request responses:
from flask import after_this_request

@app.route('/special')
def special():
    @after_this_request
    def add_special_header(response):
        response.headers['X-Special'] = 'true'
        return response
    
    return 'Special page'

Best Practices

Validate Input

Always validate and sanitize request data

Set Limits

Configure MAX_CONTENT_LENGTH to prevent DOS attacks

Use get() Method

Use .get() instead of dict access to avoid KeyError

Secure Cookies

Always use secure, httponly cookies for sensitive data