Los métodos before_request() y after_request() en Flask: Guía Completa

  Concepto básico

Los métodos before_request() y after_request() son decoradores muy útiles en Flask que nos permiten ejecutar código antes y después de cada solicitud HTTP. Son como “intermediarios” que procesan datos antes y después de que nuestra ruta principal se ejecute.

Métodos before_request()

Este decorador ejecuta una función antes de cada solicitud HTTP, incluso antes de que llegue a su ruta destino.

  Concepto básico

  • Se ejecuta ANTES de cada solicitud
  • Puede modificar datos globales
  • Puede interrumpir la solicitud retornando una respuesta
  • Es útil para validaciones o preparación de datos

Ejemplos Prácticos


1. Verificación simple de autenticación

python
from flask import Flask, g, redirect, url_for
from functools import wraps

app = Flask(__name__)

@app.before_request
def verificar_usuario():
  # Simulamos verificación de usuario
  if 'usuario' not in session:
      return redirect(url_for('login'))

2. Registro de tiempo de inicio

python
from flask import Flask
import time

app = Flask(__name__)

@app.before_request
def registrar_tiempo_inicio():
  g.start_time = time.time()
  print("Iniciando solicitud...")

3. Preparar conexión a base de datos

python
@app.before_request
def conectar_db():
  g.db = conectar_a_base_datos()
  print("Conexión a BD establecida")

Métodos after_request()

Este decorador ejecuta una función después de que se procesa la solicitud pero antes de enviar la respuesta al cliente.

  Concepto básico

  • Se ejecuta DESPUÉS de cada solicitud
  • Puede modificar la respuesta
  • Recibe y debe retornar un objeto response
  • Es útil para modificar headers o procesar la respuesta

Ejemplos Prácticos


1. Añadir headers personalizados

python
from flask import Flask

app = Flask(__name__)

@app.after_request
def add_header(response):
  response.headers['Mi-Header'] = 'Valor-Personalizado'
  return response

2. Calcular tiempo de respuesta

python
@app.after_request
def calcular_tiempo(response):
  if hasattr(g, 'start_time'):
      tiempo_total = time.time() - g.start_time
      response.headers['Tiempo-Respuesta'] = str(tiempo_total)
  return response

3. Manejo de CORS

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

Ejemplo Completo Integrado


python
from flask import Flask, g, request, session
import time

app = Flask(__name__)
app.secret_key = 'clave_secreta'

# Before request - Verificación y preparación
@app.before_request
def before_request_func():
  g.start_time = time.time()
  print(f"Nueva solicitud a: {request.path}")
  
  # Simulamos verificación de usuario
  if 'usuario' not in session and request.path != '/login':
      return "Por favor, inicie sesión", 401

# After request - Procesamiento final
@app.after_request
def after_request_func(response):
  # Calculamos tiempo de respuesta
  if hasattr(g, 'start_time'):
      tiempo_total = time.time() - g.start_time
      response.headers['X-Tiempo-Respuesta'] = f"{tiempo_total:.2f} segundos"
  
  # Agregamos headers de seguridad
  response.headers['X-Content-Type-Options'] = 'nosniff'
  return response

# Rutas de ejemplo
@app.route('/')
def home():
  return "¡Bienvenido a la página principal!"

@app.route('/login')
def login():
  session['usuario'] = 'usuario_ejemplo'
  return "Login exitoso"

@app.route('/logout')
def logout():
  session.pop('usuario', None)
  return "Logout exitoso"

# Corriendo la app 
if __name__ == '__main__':
  app.run(debug=True, port=5000)
  Casos de Uso Comunes

  1. before_request():

    • Verificar autenticación
    • Inicializar conexiones a bases de datos
    • Registrar inicio de solicitudes
    • Preparar variables globales
  2. after_request():

    • Añadir headers de seguridad
    • Modificar la respuesta
    • Registrar métricas de rendimiento
    • Cerrar conexiones a bases de datos

Consejo Práctico:

Para depuración, puedes usar ambos decoradores para crear un sistema simple de logging:

python
@app.before_request
def log_request_info():
  print("---------------------")
  print(f"Ruta: {request.path}")
  print(f"Método: {request.method}")
  print(f"Hora: {datetime.now()}")

@app.after_request
def log_response_info(response):
  print(f"Código de Estado: {response.status_code}")
  print("---------------------")
  return response