util-http es un módulo de utilidades para realizar solicitudes HTTP con diversas opciones y clientes.
ADVERTENCIA: Asegúrate de configurar correctamente las opciones del cliente antes de realizar solicitudes.
- Instalacion
- Clientes disponibles
- Configuracion del cliente (ClientConfig)
- Opciones por solicitud (ClientOptions)
- Manejo de errores (CustomError)
- AxiosClient
- FetchClient
- UndiciClient
- SuperAgentClient
- HttpClient
- TypeScript
npm install util-http
# o
pnpm add util-http| Cliente | Descripcion |
|---|---|
AxiosClient |
Basado en axios |
FetchClient |
Basado en la Fetch API nativa |
UndiciClient |
Basado en undici (alto rendimiento) |
SuperAgentClient |
Basado en superagent (isomorphic: Node.js + browser) |
HttpClient |
Agrupador que expone los cuatro clientes y utilidades estaticas |
Se pasa al constructor de cada cliente para establecer valores por defecto que se aplican a todas las solicitudes.
interface ClientConfig {
baseURL?: string;
timeout?: number;
headers?: Record<string, string>;
contentTypes?: Record<string, "json" | "urlencoded" | "formData" | "text" | "buffer">;
onError?: (error: CustomError) => CustomError;
}| Opcion | Tipo | Descripcion |
|---|---|---|
baseURL |
string |
URL base que se antepone a todas las rutas relativas |
timeout |
number |
Tiempo de espera en ms (por defecto 15000) |
headers |
Record<string, string> |
Cabeceras globales para todas las solicitudes |
contentTypes |
Record<string, ContentTypeHandlerKey> |
Extiende el mapa de Content-Type para parsear respuestas personalizadas |
onError |
(error: CustomError) => CustomError |
Hook que intercepta y transforma el error antes de lanzarlo |
import { AxiosClient } from "util-http";
const client = new AxiosClient({
baseURL: "https://api.example.com",
timeout: 5000,
headers: { Authorization: "Bearer token" },
onError: (err) => {
console.error("Request failed:", err.message);
return err;
}
});Se pasan a cada llamada individual y tienen prioridad sobre la configuracion del cliente.
interface ClientOptions {
url: string;
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
headers?: Record<string, string>;
data?: string | FormData | URLSearchParams | Record<string, unknown>;
params?: Record<string, string | number | boolean>;
timeout?: number;
responseType?: "json" | "urlencoded" | "formData" | "text" | "buffer";
}| Opcion | Tipo | Descripcion |
|---|---|---|
url |
string |
URL de la solicitud (absoluta o relativa si hay baseURL) |
method |
Method |
Metodo HTTP |
headers |
Record<string, string> |
Cabeceras adicionales (se mezclan con las globales; estas tienen prioridad) |
data |
varios | Cuerpo. FormData y URLSearchParams se envian tal cual; los objetos se serializan como JSON |
params |
Record<string, string | number | boolean> |
Parametros de query string que se adjuntan a la URL |
timeout |
number |
Sobreescribe el timeout del cliente para esta solicitud |
responseType |
ContentTypeHandlerKey |
Fuerza un parser concreto independientemente del Content-Type de la respuesta |
Todos los clientes lanzan instancias de CustomError en caso de fallo.
import { CustomError } from "util-http";
client.get({ url: "/users" }).catch((err: CustomError) => {
console.log(err.message); // mensaje de error
console.log(err.statusCode); // codigo HTTP (ej. 404, 503)
console.log(err.client); // "axios" | "fetch" | "undici"
console.log(err.timestamp); // ISO string del momento del error
console.log(err.extra); // datos adicionales de la respuesta
console.log(err.toJSON()); // representacion completa como objeto plano
err.log(); // imprime el error formateado en consola
});Mapeos automaticos:
| Condicion | statusCode |
message |
|---|---|---|
ECONNREFUSED o respuesta HTML |
503 |
"Unavailable Service" |
ENOTFOUND o mensaje vacio |
404 |
"Resource Not Found" |
| Resto de errores | el del servidor | el del servidor |
Cliente basado en axios. Soporta todos los formatos de respuesta de axios incluido arraybuffer.
client.get<T>(options)
client.post<T>(options)
client.put<T>(options)
client.patch<T>(options)
client.delete<T>(options)
client.head(options) // devuelve Record<string, string> con las cabeceras
client.options<T>(options)
client.request<T>(options) // incluye "method" en las opcionesimport { AxiosClient } from "util-http";
const client = new AxiosClient({
baseURL: "https://api.example.com",
headers: { Authorization: "Bearer token" }
});
// GET con parametros de query
const users = await client.get<User[]>({
url: "/users",
params: { page: 1, limit: 20 }
});
// POST con cuerpo JSON
const user = await client.post<User>({
url: "/users",
data: { name: "Alice", email: "alice@example.com" }
});
// GET de un archivo binario
const file = await client.get<ArrayBuffer>({
url: "/files/report.pdf",
responseType: "buffer"
});
// Usando request() directamente
const result = await client.request<User>({ url: "/users/1", method: "GET" });Cliente basado en la Fetch API nativa. Usa AbortSignal.timeout() para el control de tiempo de espera.
client.get<T>(options)
client.post<T>(options)
client.put<T>(options)
client.patch<T>(options)
client.delete<T>(options)
client.request<T>(options)import { FetchClient } from "util-http";
const client = new FetchClient({
baseURL: "https://api.example.com",
timeout: 8000,
contentTypes: { "application/vnd.api+json": "json" } // Content-Types personalizados
});
// Subir un fichero con FormData (no se serializa como JSON)
const formData = new FormData();
formData.append("avatar", file);
await client.post({ url: "/users/1/avatar", data: formData });
// Forzar lectura como texto independientemente del Content-Type
const html = await client.get<string>({
url: "/page",
responseType: "text"
});Cliente basado en undici, el cliente HTTP de alto rendimiento de Node.js. Usa bodyTimeout y headersTimeout para el control de tiempo de espera.
client.get<T>(options)
client.post<T>(options)
client.put<T>(options)
client.patch<T>(options)
client.delete<T>(options)
client.request<T>(options)import { UndiciClient } from "util-http";
const client = new UndiciClient({
baseURL: "https://api.example.com",
timeout: 10000
});
// POST con URLSearchParams (se convierte a string automaticamente)
const params = new URLSearchParams({ grant_type: "client_credentials" });
const token = await client.post<TokenResponse>({
url: "/oauth/token",
data: params
});
// GET con query string
const results = await client.get<SearchResult[]>({
url: "/search",
params: { q: "typescript", sort: "stars" }
});Cliente basado en superagent. Funciona tanto en Node.js como en el browser (isomorphic), lo que lo hace util para librerias universales.
client.get<T>(options)
client.post<T>(options)
client.put<T>(options)
client.patch<T>(options)
client.delete<T>(options)
client.request<T>(options)import { SuperAgentClient } from "util-http";
const client = new SuperAgentClient({
baseURL: "https://api.example.com",
timeout: 5000,
headers: { Authorization: "Bearer token" }
});
// GET con parametros de query
const users = await client.get<User[]>({
url: "/users",
params: { page: 1, active: true }
});
// POST con cuerpo JSON
const user = await client.post<User>({
url: "/users",
data: { name: "Alice", email: "alice@example.com" }
});
// POST con FormData (los campos se envian via .field())
const formData = new FormData();
formData.append("avatar", file);
await client.post({ url: "/users/1/avatar", data: formData });
// GET de un archivo binario
const file = await client.get<ArrayBuffer>({
url: "/files/report.pdf",
responseType: "buffer"
});Agrupador que instancia los cuatro clientes con la misma configuracion. Tambien expone utilidades estaticas para construir URLs y parsear respuestas.
import { HttpClient } from "util-http";
// Con configuracion compartida para los tres clientes
const http = new HttpClient({
baseURL: "https://api.example.com",
timeout: 5000
});
await http.axios.get({ url: "/users" });
await http.fetch.post({ url: "/users", data: { name: "Bob" } });
await http.undici.get({ url: "/health" });
await http.superagent.get({ url: "/status" });
// Instancia singleton (sin configuracion)
const singleton = HttpClient.getInstance();// Construye una URL completa concatenando baseURL y path
HttpClient.buildUrl("https://api.example.com", "/users");
// => "https://api.example.com/users"
// Construye URL con query string a partir de un objeto
HttpClient.buildUrlWithParams("https://api.example.com", "/search", { q: "ts", page: 1 });
// => "https://api.example.com/search?q=ts&page=1"
// Crea un mapa de handlers para parsear el body de la respuesta
const handlers = HttpClient.createContentHandlers();
// handlers.json(body) => body.json()
// handlers.text(body) => body.text()
// handlers.buffer(body) => body.arrayBuffer()
// Normaliza cualquier error a una instancia de CustomError
const err = HttpClient.handleErrors(rawError, 500, "fetch");Todos los tipos publicos se pueden importar directamente:
import type { ClientConfig, ClientOptions, ContentTypeHandlerKey, Client, Method } from "util-http";
import { CustomError, Constants } from "util-http";type ContentTypeHandlerKey = "json" | "urlencoded" | "formData" | "text" | "buffer";Mapa completo de tipos MIME a ContentTypeHandlerKey incluido por defecto:
import { Constants } from "util-http";
console.log(Constants.contentTypes["application/json"]); // "json"
console.log(Constants.contentTypes["multipart/form-data"]); // "formData"
console.log(Constants.contentTypes["application/octet-stream"]); // "buffer"