Last modified: Nov 15, 2024 By Alexander Williams

Flask after_request: Process Responses After Each Request

In Flask, after_request() is a powerful decorator that allows you to execute functions after each request is processed but before sending the response to the client. This functionality is crucial for response modification and cleanup tasks.

Basic Usage of after_request

The after_request decorator works in conjunction with Flask's before_request to create a complete request handling pipeline. Here's a basic example:


from flask import Flask, request

app = Flask(__name__)

@app.after_request
def after_request(response):
    response.headers['X-Custom-Header'] = 'Custom Value'
    return response

@app.route('/')
def home():
    return 'Hello, World!'

Common Use Cases

The after_request decorator is particularly useful for tasks like adding headers, logging, and modifying responses. It works seamlessly with Flask's response handling.

1. Adding CORS Headers


@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
    return response

2. Response Logging


@app.after_request
def log_response(response):
    app.logger.info(f'Response Status: {response.status}')
    return response

Working with Response Objects

The after_request function must always return the response object. You can modify the response but shouldn't create a new one. Here's an example that adds compression:


import gzip
from io import BytesIO

@app.after_request
def compress_response(response):
    if response.headers.get('Content-Type') == 'text/html':
        compressed = BytesIO()
        with gzip.GzipFile(fileobj=compressed, mode='wb') as gz:
            gz.write(response.data)
        response.data = compressed.getvalue()
        response.headers['Content-Encoding'] = 'gzip'
    return response

Error Handling

When using after_request, it's important to handle potential errors properly. You can use it with Flask's error handling system:


@app.after_request
def handle_errors(response):
    if response.status_code >= 400:
        app.logger.error(f'Request failed with status {response.status_code}')
    return response

Best Practices

Keep after_request functions lightweight to avoid performance impacts. Focus on necessary modifications and avoid complex operations that could delay response time.

Always ensure your after_request functions return the response object. Failing to do so will result in application errors.

Conclusion

Flask's after_request decorator is a powerful tool for response manipulation and request cleanup. When used correctly, it provides a clean way to implement cross-cutting concerns across your application.