- ¿Qué es un middleware?
- ¿Cómo funcionan las middlewares?
- Flask: Usando middlewares
- Agregar headers con middlewares
- ¿Qué pasa si quiero detener la ejecución?
- Ejecutar código siempre (incluso con errores)
- Relación con los handlers
En una aplicación web, algunas tareas deben ejecutarse en cada request, como validar usuarios, registrar visitas o comprobar parámetros. Repetir código en todas partes no es práctico ni seguro. Para eso existen los middlewares, que nos ayudan a manejar estas tareas de forma centralizada. Veamos cómo funcionan.
¿Qué es un middleware?
Tareas típicas de una middleware
| Tarea | Cuándo se usa |
|---|---|
| Verificar acceso | Antes del request |
| Registrar logs | Antes o después de cada request |
| Agregar headers extras | Antes de enviar respuesta |
| Manejar errores | Cuando ocurre una excepción en el servidor |
¿Cómo funcionan las middlewares?
Supongamos que tenemos esta función:
def add_five(num):
return num + 5
Si queremos "decorarla" para que antes de sumar 5 primero duplique el número, podríamos hacer esto:
def double_and_add_five(x):
return add_five(x * 2)
print(double_and_add_five(3)) # Resultado: 11
Lo que hicimos aquí fue envolver la función add_five dentro de otra. Esta técnica se llama composición y es muy similar a cómo funcionan las middlewares.
Flask: Usando middlewares
Flask ya viene listo para usar middlewares. Lo único que tenemos que hacer es usar algunos decoradores especiales:
| Decorador | Cuándo se ejecuta |
|---|---|
@before_request |
Antes de ejecutar el handler |
@after_request |
Después de ejecutar el handler |
@teardown_request |
Siempre se ejecuta, incluso si hubo un error |
⏬ Ejemplo básico
from flask import Flask, request
app = Flask(__name__)
@app.before_request
def log_request_path():
print(f"Path: {request.path}")
@app.after_request
def log_response(response):
print("Respuesta enviada al cliente")
return response
@app.route("/")
def home():
return "Hola, estás en la página principal"
Este código sirve para:
- Imprimir en consola el path de cada petición.
- Mostrar un mensaje cuando la respuesta haya sido enviada.
Cada middleware se ejecuta en una cadena (uno tras otro). Flask recorre esa cadena para cada request.
Agregar headers con middlewares
También podemos modificar la respuesta desde una middleware, como agregar headers personalizados:
@app.after_request
def add_custom_header(response):
response.headers["X-Custom-Header"] = "valor"
return response
Probemos esto con un comando:
curl --head localhost:5000
Y veremos algo como:
HTTP/1.1 200 OK
X-Custom-Header: valor
¿Qué pasa si quiero detener la ejecución?
Hay veces en que no queremos que se siga ejecutando todo el código. Por ejemplo, que se detenga si falta un parámetro obligatorio en la URL.
Podemos hacerlo retornando una respuesta directamente desde una middleware:
@app.before_request
def check_id():
if request.endpoint == 'resource':
id = request.args.get("id")
if not id:
return 'Falta parámetro "id"', 400
400 (Bad Request).
Código completo del ejemplo:
from flask import Flask, request
app = Flask(__name__)
@app.before_request
def check_id():
if request.endpoint == "resource":
id = request.args.get("id")
if not id:
return 'Falta parámetro "id"', 400
@app.route("/resource")
def resource():
id = request.args.get("id")
return f"Recurso con id: {id}"
Si ejecutamos:
curl localhost:5000/resource
Veremos:
HTTP/1.1 400 BAD REQUEST
Falta parámetro "id"
Este patrón se conoce como Cadena de Responsabilidad.
Ejecutar código siempre (incluso con errores)
Flask tiene una middleware especial llamada @teardown_request. Se ejecuta al final del ciclo, incluso si ocurrió un error.
@app.teardown_request
def cleanup(exception):
print("Esto se ejecuta siempre, sin importar si hubo error.")
@app.route("/")
def home():
raise Exception("¡Algo salió mal!")
Cuando haces un request:
curl -Is localhost:5000/
Aunque veas un error 500, en consola aparecerá:
Esto se ejecuta siempre, sin importar si hubo error.
Relación con los handlers
Ten en cuenta que las funciones que responden a rutas (como @app.route('/') ) también son middlewares, pero esas solo se ejecutan si el request coincide con esa ruta específica.
Flask ejecuta las middlewares en orden:
- Todas las middlewares de
@before_request - El manejador (
@app.route) - Todas las middlewares de
@after_request - La middleware
@teardown_request
Resumen
- Los middlewares en Flask son funciones que se ejecutan antes o después de los handlers.
@before_requestse ejecuta antes de procesar el request.@after_requestse ejecuta después de procesar el request y puede modificar la respuesta.@teardown_requestsiempre se ejecuta, incluso si hubo errores.- Un middleware puede detener el flujo retornando una respuesta directamente.
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.