@authuser/http-core
v1.0.2
Published
Módulo base para gestionar peticiones HTTP con arquitectura por middlewares, soportando:
Readme
@authuser/http-core
Módulo base para gestionar peticiones HTTP con arquitectura por middlewares, soportando:
- Retry automático
- Caché persistente de respuestas
- Deduplicación de peticiones simultáneas
- Rate limiting
- Métricas personalizadas
- Sesión opcional para autenticación
Instalación
npm install @authuser/http-coreConstructor del HttpService
El constructor recibe un objeto HttpServiceOptions con las siguientes propiedades:
| Atributo | Tipo | Obligatorio | Descripción |
| ------------- | --------------------- | ----------- | ---------------------------------------------------------------------------------------- |
| client | HttpClientPort | ✅ Sí | Cliente HTTP que implementa request(). Ej: AxiosHttpClient. |
| session | SessionManagerPort? | ❌ No | (Opcional) Gestor de sesión JWT (token/refresh/logout). Por defecto: NoSessionManager. |
| config | CoreConfig? | ❌ No | (Opcional) Configuración global del servicio HTTP (ver más abajo). |
| cache | CachePort? | ❌ No | (Opcional) Implementación para persistir la caché. Por defecto: MemoryCache. |
| logLevel | LogLevel[]? | ❌ No | (Opcional) Niveles de log activos: 'error', 'warn', 'info', 'debug'. |
| middlewares | Middleware[]? | ❌ No | (Opcional) Middlewares personalizados que se ejecutan antes de los internos. |
Configuración (CoreConfig)
| Propiedad | Tipo | Obligatorio | Descripción |
| --------------- | -------------------------------------------------- | ----------- | ---------------------------------------------------------------------------- |
| baseUrl | string | ✅ Sí | URL base para peticiones relativas. |
| retry | RetryConfig? | ❌ No | Configura reintentos automáticos (ver más abajo). Por defecto deshabilitado. |
| cache | { enabled: boolean; ttlMs: number; maxEntries? } | ❌ No | Activa caché por TTL. También se puede habilitar por petición. |
| rateLimit | { requests: number; perMs: number } | ❌ No | Define número máximo de peticiones por intervalo (tokens/intervalo). |
| metrics | MetricsPort | ❌ No | Callbacks para medir rendimiento: onRequestStart? y onRequestEnd?. |
| commonHeaders | Record<string, string> | ❌ No | Cabeceras comunes aplicadas a todas las peticiones (solo URLs no externas). |
RetryConfig
type RetryConfig = {
enabled?: boolean; // activar/desactivar retry
maxAttempts?: number; // número máximo de reintentos
delay?: number; // retardo base en ms
backoff?: 'linear' | 'exponential' | 'fixed'; // tipo de backoff
skipOnStatusCode?: number[]; // evitar retry si status es uno de estos
skipOnEndpoint?: string[]; // evitar retry si URL contiene uno de estos strings
onRetry?: (retryCount: number, error: AxiosError, config: any) => void; // callback opcional
};Uso básico
import { HttpService } from '@authuser/http-core';
import { AxiosHttpClient } from '@authuser/http-core/infrastructure';
import { LocalSessionManager } from '@authuser/http-core/infrastructure';
const http = new HttpService({
client: new AxiosHttpClient(),
session: new LocalSessionManager(), // opcional
config: {
baseUrl: 'https://api.example.com',
retry: {
enabled: true,
maxAttempts: 2,
delay: 300,
backoff: 'exponential',
skipOnEndpoint: ['/auth/login'],
skipOnStatusCode: [401, 429],
},
cache: { enabled: true, ttlMs: 60_000 },
rateLimit: { requests: 10, perMs: 1_000 },
metrics: {
onRequestStart: (key) => console.log('start:', key),
onRequestEnd: (key, time, success) => console.log('end:', key, time, success),
},
},
});Ejemplo de petición
const response = await http.request({
url: '/users',
method: 'GET',
cache: true, // puede forzar cache local
requiresAuth: true, // solo si necesitas token de sesión
});Middlewares personalizados
Puedes inyectar middlewares personalizados para extender el comportamiento del servicio HTTP. Los middlewares personalizados se ejecutan antes de los middlewares internos.
Definición de un Middleware
type Middleware<T = unknown, B = unknown> = (
req: HttpRequest<B>,
next: () => Promise<HttpResponse<T>>
) => Promise<HttpResponse<T>>;Ejemplo: Inyectar headers dinámicamente
import { HttpService, Middleware } from '@authuser/http-core';
const customHeaderMiddleware: Middleware = async (req, next) => {
// Modificar el request antes de continuar
req.headers = {
...req.headers,
'X-Request-ID': crypto.randomUUID(),
'X-Timestamp': Date.now().toString(),
};
return next();
};
const http = new HttpService({
client: new AxiosHttpClient(),
middlewares: [customHeaderMiddleware],
});Ejemplo: Logging personalizado
const loggingMiddleware: Middleware = async (req, next) => {
console.log(`→ [${req.method}] ${req.url}`);
const start = Date.now();
try {
const response = await next();
const duration = Date.now() - start;
console.log(`← [${response.status}] ${req.url} (${duration}ms)`);
return response;
} catch (error) {
const duration = Date.now() - start;
console.error(`✗ [ERROR] ${req.url} (${duration}ms)`, error);
throw error;
}
};Ejemplo: Transformación de respuestas
const transformMiddleware: Middleware = async (req, next) => {
const response = await next();
// Transformar la respuesta antes de devolverla
return {
...response,
data: {
...response.data,
timestamp: new Date().toISOString(),
},
};
};Combinando múltiples middlewares
const http = new HttpService({
client: new AxiosHttpClient(),
middlewares: [
loggingMiddleware, // Se ejecuta primero
customHeaderMiddleware, // Después este
transformMiddleware, // Y finalmente este
],
});Middlewares incluidos (orden de ejecución)
Los middlewares se ejecutan en el siguiente orden:
- Middlewares personalizados (en el orden que los pasaste)
- persistenceMw: Gestiona persistencia offline-first (si está configurado)
- cacheMw: Busca en caché antes de hacer la petición y almacena la respuesta si
cacheestá activo - dedupeMw: Evita peticiones duplicadas simultáneas (deduplicación)
- rateMw: Limita el número de peticiones por intervalo usando token bucket
- metricsMw: Mide el tiempo de cada petición y ejecuta callbacks
onRequestStartyonRequestEnd - httpMw: Ejecuta el cliente HTTP real (Axios, Fetch...) con lógica de retry y refresh token automático
Tipos principales
HttpRequest<TBody>
interface HttpRequest<TBody = unknown> {
readonly url: string;
readonly method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
readonly headers?: Record<string, string>;
readonly query?: Record<string, string | number | boolean>;
readonly body?: TBody;
readonly requiresAuth?: boolean; // Incluye automáticamente el token JWT
readonly cache?: boolean; // Forzar uso de caché para esta petición
readonly cacheTtlMs?: number; // TTL específico para esta petición
readonly signal?: AbortSignal; // Cancelación de peticiones
}HttpResponse<T>
interface HttpResponse<T = unknown> {
status: number;
data: T;
headers: Record<string, string>;
}HttpError
class HttpError extends Error {
status: number;
request: HttpRequest;
response?: unknown;
}Características avanzadas
- Refresh Token automático: Si una petición devuelve 401 y tiene
requiresAuth: true, intenta refrescar el token automáticamente una vez. - URLs externas: Si la URL comienza con
http://ohttps://, no se aplican lascommonHeaders. - Logging por niveles: Configura
logLevelen el constructor para ver logs deerror,warn,info, odebug. - Cancelación de peticiones: Usa
AbortControllery pasa elsignalen elHttpRequest.
Arquitectura
Este módulo sigue una arquitectura hexagonal:
- Domain: Puertos (interfaces) que definen contratos.
- Application: Lógica de negocio (
HttpService,Config). - Infrastructure: Adaptadores concretos (
AxiosHttpClient,CacheManager,LocalSessionManager).
Este módulo es la base para @authuser/http-react y @authuser/http-react-native.
