Skip to main content

Global Handler es una librería Python diseñada para facilitar el manejo de errores, validaciones de requests y métricas en aplicaciones web

Project description

Global Handler

Descripción

Global Handler es una librería Python completa para el manejo robusto de aplicaciones web basadas en Flask. Proporciona herramientas esenciales para validar datos de entrada, gestionar errores de manera elegante, y monitorear el rendimiento de tus endpoints. Diseñada para desarrolladores que buscan una solución integrada y fácil de usar para mejorar la calidad y mantenibilidad de sus APIs REST.

Características Principales

  • Validación Automática de Requests: Usa Pydantic para validar JSON, parámetros de query y headers con decoradores simples.
  • Sistema de Excepciones HTTP Estructurado: Excepciones personalizadas con códigos de error consistentes y mensajes descriptivos.
  • Middlewares de Métricas: Logging automático de requests con tiempos de ejecución y detalles de contexto.
  • Manejo Global de Errores: Respuestas de error estandarizadas en formato JSON.
  • Integración Fluida con Flask: Diseñado específicamente para aplicaciones Flask, sin configuración compleja.

Instalación

Requisitos

  • Python 3.13+
  • Flask
  • Pydantic

Instalación desde PyPI

pip install global-handler

Instalación desde código fuente

git clone https://github.com/tu-usuario/global-handler.git
cd global-handler
poetry install

Implementación en una Aplicación Flask

Configuración Básica

  1. Importa los componentes necesarios:
from flask import Flask
from global_handler.decorators.request_decorators import validate_with, validate_query_with, validate_headers_with
from global_handler.decorators.error_handler import register_error_handlers
from global_handler.middlewares.metrics_middleware import before_request_metrics, after_request_metrics
from global_handler.exceptions.http_exceptions import ValidationHttpError
from pydantic import BaseModel
  1. Crea tu aplicación Flask:
app = Flask(__name__)

# Registra los manejadores de errores
register_error_handlers(app)

# Registra los middlewares de métricas
app.before_request(before_request_metrics)
app.after_request(after_request_metrics)

Uso de Decoradores de Validación

Validación del Cuerpo JSON (validate_with)

Valida automáticamente el cuerpo JSON de las requests POST/PUT contra un modelo Pydantic.

  • Los decoradores son compatibles con funciones síncronas y con async def cuando el framework lo soporte.
class UserCreateModel(BaseModel):
    name: str
    email: str
    age: int

@app.route('/users', methods=['POST'])
@validate_with(UserCreateModel)
def create_user(validated_data):
    # validated_data es una instancia de UserCreateModel con datos validados
    user = User(name=validated_data.name, email=validated_data.email, age=validated_data.age)
    # ... lógica para guardar usuario
    return {"message": "Usuario creado", "user_id": user.id}, 201

Comportamiento:

  • Si el JSON es inválido: retorna 400 con código "INVALID_JSON"
  • Si falla la validación: retorna 400 con código "VALIDATION_ERROR" y detalles de los errores

Validación de Parámetros Query (validate_query_with)

Valida los parámetros de la URL query string.

class UserQueryModel(BaseModel):
    page: int = 1
    limit: int = 10
    search: str = None

@app.route('/users', methods=['GET'])
@validate_query_with(UserQueryModel)
def list_users(query_params):
    users = User.query.filter_by(search=query_params.search).paginate(
        page=query_params.page, per_page=query_params.limit
    )
    return {"users": [user.to_dict() for user in users.items]}, 200

Comportamiento:

  • Parámetros faltantes: usa valores por defecto del modelo
  • Tipos inválidos: retorna 400 con código "INVALID_PARAMETER"
  • Parámetros requeridos faltantes: retorna 400 con código "MISSING_PARAMETER"

Validación de Headers (validate_headers_with)

Valida los headers HTTP de la request.

from pydantic import Field

class AuthHeadersModel(BaseModel):
    authorization: str = Field(alias="Authorization")
    content_type: str = Field(alias="Content-Type", default="application/json")

@app.route('/protected', methods=['GET'])
@validate_headers_with(AuthHeadersModel)
def protected_route(headers_data):
    token = headers_data.authorization.replace("Bearer ", "")
    # ... lógica de autenticación
    return {"message": "Acceso autorizado"}, 200

Nota: Usa Field(alias="Header-Name") para mapear nombres de headers con guiones a nombres de campos válidos en Python.

Middlewares de Métricas

Los middlewares registran automáticamente información sobre cada request:

  • before_request_metrics: Registra el inicio de la request con método, path, parámetros query y ID de request.
  • after_request_metrics: Registra el final con tiempo de ejecución, código de estado y detalles adicionales.

Los logs se envían al sistema logger_tracker configurado.

  • La librería también incluye ayudantes async de métricas: before_request_metrics_async y after_request_metrics_async, diseñados para integrar tracing y métricas en rutas y workers nativos asíncronos.

Manejo de Errores

La librería incluye manejadores de errores globales que convierten excepciones en respuestas JSON estandarizadas, con controles de fuga de información según el entorno:

{
  "error": {
    "message": "Invalid request body",
    "code": "VALIDATION_ERROR",
    "details": [
      {
        "field": "age",
        "error_type": "int_parsing",
        "error": "Input should be a valid integer"
      }
    ]
  },
  "request_id": "..."
}
  • En modo desarrollo (GLOBAL_HANDLER_DEBUG=true), la librería puede exponer detalles de validación y trazas controladas.
  • En modo producción (GLOBAL_HANDLER_ENV=production), los detalles internos se omiten automáticamente para prevenir fugas de información.
  • El comportamiento también puede personalizarse con GLOBAL_HANDLER_SANITIZE_ERRORS=false cuando se requiera imprimir más contexto en entornos no productivos.

Mapeo de Excepciones de Dominio

Global Handler permite mapear excepciones de dominio aisladas del stack web a respuestas HTTP concretas. Registra las excepciones de negocio usando register_error_handlers(app, exception_mappings={...}) o register_exception_mapping():

from flask import Flask
from global_handler.decorators.error_handler import register_error_handlers
from global_handler.exceptions.http_exceptions import NotFoundHttpError

class ResourceNotFoundException(Exception):
    pass

app = Flask(__name__)
register_error_handlers(
    app,
    exception_mappings={
        ResourceNotFoundException: NotFoundHttpError,
    },
)

Con esto, una excepción de dominio como ResourceNotFoundException se convierte en un 404 con código NOT_FOUND, manteniendo la lógica HTTP fuera del dominio.

Excepciones Disponibles

  • ValidationHttpError: Errores de validación de datos (400)
  • InvalidJsonHttpError: JSON malformado (400)
  • MissingParameterHttpError: Parámetros requeridos faltantes (400)
  • InvalidParameterHttpError: Parámetros con tipos inválidos (400)
  • UnauthorizedHttpError: Autenticación requerida (401)
  • InvalidCredentialsHttpError: Credenciales inválidas (401)
  • TokenExpiredHttpError: Token expirado (401)
  • ForbiddenHttpError: Acceso prohibido (403)
  • NotFoundHttpError: Recurso no encontrado (404)
  • Y más...

Ejemplo Completo de Aplicación

from flask import Flask
from global_handler.decorators.request_decorators import validate_with, validate_query_with
from global_handler.decorators.error_handler import register_error_handlers
from global_handler.middlewares.metrics_middleware import before_request_metrics, after_request_metrics
from pydantic import BaseModel

app = Flask(__name__)

# Configuración
register_error_handlers(app)
app.before_request(before_request_metrics)
app.after_request(after_request_metrics)

# Variables de entorno opcionales
# - GLOBAL_HANDLER_DEBUG=true
# - GLOBAL_HANDLER_ENV=development|production
# - GLOBAL_HANDLER_SANITIZE_ERRORS=false

# Modelos
class UserCreateModel(BaseModel):
    name: str
    email: str
    age: int

class UserQueryModel(BaseModel):
    page: int = 1
    limit: int = 10

# Rutas
@app.route('/users', methods=['POST'])
@validate_with(UserCreateModel)
def create_user(validated_data):
    # Lógica de negocio
    return {"message": "Usuario creado", "data": validated_data.model_dump()}, 201

@app.route('/users', methods=['GET'])
@validate_query_with(UserQueryModel)
def list_users(query_params):
    # Lógica de negocio
    return {"users": [], "pagination": query_params.model_dump()}, 200

if __name__ == '__main__':
    app.run(debug=True)

Detalles Técnicos

  • Lenguaje: Python 3.13+
  • Framework: Flask
  • Validación: Pydantic v2
  • Logging: Integración con logger_tracker
  • Build System: Poetry
  • Licencia: MIT

Dependencias

  • Flask>=2.0.0
  • Pydantic>=2.0.0
  • logger-tracker>=1.0.9

Estructura del Proyecto

src/global_handler/
├── decorators/
│   ├── error_handler.py      # Manejadores de errores globales
│   └── request_decorators.py # Decoradores de validación
├── exceptions/
│   └── http_exceptions.py    # Excepciones HTTP
└── middlewares/
    └── metrics_middleware.py # Middlewares de métricas

Contribución

  1. Fork el proyecto
  2. Crea una rama para tu feature (git checkout -b feature/AmazingFeature)
  3. Commit tus cambios (git commit -m 'Add some AmazingFeature')
  4. Push a la rama (git push origin feature/AmazingFeature)
  5. Abre un Pull Request

Licencia

Este proyecto está bajo la Licencia MIT. Ver el archivo LICENSE para más detalles.

Soporte

Para preguntas o soporte, por favor abre un issue en GitHub o contacta al maintainer. pyproject.toml # Configuración del proyecto con Poetry


### Instalación

1. Clona el repositorio:
   ```bash
   git clone <url-del-repositorio>
   cd global-handler
  1. Instala las dependencias con Poetry:
    poetry install
    

Uso

Configuración en Flask

from flask import Flask
from global_handler.decorators.error_handler import register_error_handlers
from global_handler.middlewares.metrics_middleware import before_request_metrics, after_request_metrics

app = Flask(__name__)

# Registrar middlewares
app.before_request(before_request_metrics)
app.after_request(after_request_metrics)

# Registrar manejadores de errores
register_error_handlers(app)

Uso de Decoradores

from pydantic import BaseModel
from global_handler.decorators.request_decorators import validate_with

class UserModel(BaseModel):
    name: str
    age: int

@app.route('/user', methods=['POST'])
@validate_with(UserModel)
def create_user(validated_data):
    # validated_data es una instancia de UserModel
    return {"message": "User created"}
from global_handler.decorators.request_decorators import validate_headers_with

class HeaderModel(BaseModel):
    Authorization: str
    Content_Type: str

@app.route('/protected', methods=['GET'])
@validate_headers_with(HeaderModel)
def protected_route(headers_data):
    # headers_data es una instancia de HeaderModel
    return {"message": "Access granted"}

Excepciones

from global_handler.exceptions.http_exceptions import ValidationHttpError

raise ValidationHttpError("Invalid data")

Tests

El proyecto incluye un conjunto de tests unitarios para validar el funcionamiento de los componentes.

Ejecutar Tests

Instala las dependencias de desarrollo:

poetry install --with dev

Ejecuta los tests con pytest:

pytest

Cobertura de Tests

  • test_exceptions.py: Valida las excepciones HTTP personalizadas.
  • test_request_decorators.py: Prueba los decoradores de validación (body, query, headers) con mocks de Flask.
  • test_error_handler.py: Verifica el registro y manejo de errores.
  • test_metrics_middleware.py: Confirma el logging de métricas.

Contribución

Para contribuir, por favor crea un issue o pull request en el repositorio.

Licencia

Este proyecto está bajo la Licencia MIT. Ver archivo LICENSE para más detalles.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

global_handler-1.0.5.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

global_handler-1.0.5-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file global_handler-1.0.5.tar.gz.

File metadata

  • Download URL: global_handler-1.0.5.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.13.13 Linux/6.17.0-1015-azure

File hashes

Hashes for global_handler-1.0.5.tar.gz
Algorithm Hash digest
SHA256 bcbaff866702a282e161805d4e86b6c51be4b8e113c82f51f3edde932ba93903
MD5 49f9a8fec39f537c91729effc7c3e961
BLAKE2b-256 11383d2ae9303637ea8244e64674bfe3050e17a7e25ee94d886625baac0bbc6f

See more details on using hashes here.

File details

Details for the file global_handler-1.0.5-py3-none-any.whl.

File metadata

  • Download URL: global_handler-1.0.5-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.4 CPython/3.13.13 Linux/6.17.0-1015-azure

File hashes

Hashes for global_handler-1.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 e7b6b2ace49bfae077f3d5abe8a8ec825b402bd85b924e5cc45a2f539577882d
MD5 f40cfa126255569831af2e84db33495e
BLAKE2b-256 30b734665211b27b3c5555ebf3bd5138754becdcacc7186120020a822b45deda

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page