Capítulo 27 — HTTP Functions y Callable Functions¶
Recursos visuales propuestos¶
Antes de desarrollar el capítulo conviene separar los recursos que enseñan conceptos operativos de aquellos que representan arquitectura técnica. La comparación entre HTTP Functions y Callable Functions, el flujo básico de una petición HTTP, el flujo de una Callable Function, los ejemplos de intercambio de datos y los casos de uso se entienden mejor mediante imágenes didácticas, porque su función principal es construir intuición progresiva. En cambio, la arquitectura de una HTTP Function, la arquitectura de una Callable Function, el flujo completo Cliente → Function → Firestore y la integración entre Authentication, Functions y APIs externas deben representarse como diagramas SVG, ya que muestran relaciones entre componentes, rutas de ejecución y responsabilidades técnicas que requieren precisión estructural.[cite:1][cite:2]
Imágenes didácticas¶
- Comparación HTTP vs Callable. Debe ser imagen didáctica porque busca fijar criterios de decisión.
- Flujo básico de una petición HTTP. Conviene como imagen didáctica porque explica el recorrido general solicitud-respuesta.
- Flujo de una Callable Function. Es mejor como imagen didáctica porque resume un flujo ya mediado por el SDK.
- Ejemplos de intercambio de datos. Deben ser imágenes didácticas porque ayudan a comprender payloads, respuestas y errores.
- Casos de uso. Conviene como imagen didáctica porque clasifica escenarios apropiados para cada tipo de función.
Diagramas SVG¶
- Arquitectura HTTP Function. Debe ser SVG porque involucra cliente, endpoint, middleware, validación, backend y servicios integrados.[cite:2]
- Arquitectura Callable Function. Debe ser SVG porque requiere mostrar el papel del Firebase SDK, la serialización, el contexto de autenticación y la respuesta tipificada.[cite:1]
- Flujo completo Cliente → Function → Firestore. Debe ser SVG porque expresa una secuencia técnica entre capas.
- Integración entre Authentication, Functions y APIs externas. Conviene como SVG porque representa relaciones multipunto de seguridad e integración.
Objetivos de aprendizaje¶
Al finalizar este capítulo, el lector será capaz de:
- Comprender qué es una HTTP Function y qué es una Callable Function en Cloud Functions v2.[cite:1][cite:2]
- Identificar las diferencias reales entre consumir una función mediante HTTP directo o mediante el Firebase SDK.[cite:1][cite:2]
- Diseñar endpoints serverless seguros, mantenibles y alineados con buenas prácticas de APIs modernas.
- Elegir entre JavaScript moderno y TypeScript según el contexto del proyecto y el nivel de control requerido.
- Integrar Functions con Firestore, Authentication, Cloud Storage, Hosting y APIs externas dentro del proyecto oficial del libro.
- Aplicar criterios de rendimiento, seguridad, costos y escalabilidad al diseñar lógica backend.
Introducción¶
En el capítulo anterior se explicó qué es Cloud Functions para Firebase y por qué constituye la puerta de entrada al backend serverless dentro del ecosistema Firebase. Ese conocimiento permite entender la infraestructura. Ahora corresponde aprender a construir servicios concretos sobre esa base.
Cuando una aplicación necesita lógica del lado del servidor, una de las primeras preguntas arquitectónicas es cómo va a exponerla. En Firebase, dos de las opciones más importantes son las HTTP Functions y las Callable Functions. Ambas corren en Cloud Functions v2, ambas permiten implementar lógica backend y ambas pueden integrarse con el resto del ecosistema. Sin embargo, no fueron diseñadas para resolver exactamente los mismos problemas.[cite:1][cite:2]
Una HTTP Function se comporta como un endpoint HTTP tradicional. Recibe solicitudes con métodos como GET, POST, PUT, DELETE u OPTIONS, permite manipular headers, query strings y body, y devuelve respuestas HTTP normales con sus códigos de estado correspondientes.[cite:2] Una Callable Function, en cambio, está pensada para ser invocada desde una app Firebase mediante el SDK de cliente. El SDK incluye automáticamente tokens de Authentication, FCM y App Check cuando están disponibles, y la plataforma deserializa el body y valida los tokens de forma integrada.[cite:1]
Dicho de otra forma, una HTTP Function se acerca más al modelo clásico de API REST o endpoint HTTP. Una Callable Function se acerca más al modelo de “operación remota” dentro del ecosistema Firebase: el cliente llama una función por nombre y la plataforma se encarga del protocolo de transporte, parte de la autenticación y cierta normalización de errores.[cite:1][cite:2]
Este capítulo explica ambas opciones con profundidad profesional. El objetivo no es solo aprender a crear endpoints, sino entender cuándo conviene cada enfoque, cómo diseñar seguridad básica, cómo organizar el código para producción y cómo integrar este backend con el proyecto transversal del libro.
Desarrollo completo¶
HTTP Functions¶
¿Qué es una HTTP Function?¶
Una HTTP Function es una función serverless expuesta mediante una URL única y activada por una solicitud HTTP. La documentación oficial indica que puede manejar, entre otros, los métodos GET, POST, PUT, DELETE y OPTIONS.[cite:2]
Desde un punto de vista arquitectónico, una HTTP Function es el equivalente serverless de un endpoint web. El cliente realiza una petición HTTP y la función recibe un objeto de solicitud y un objeto de respuesta. A partir de ahí, el desarrollador decide qué hacer con parámetros, body, headers, autenticación, validación, integración con otros servicios y estructura de salida.
Arquitectura¶
La arquitectura conceptual de una HTTP Function v2 puede verse así:
- El cliente realiza una solicitud HTTP.
- La solicitud llega a la URL de la función.
- Cloud Functions v2 enruta la solicitud al servicio correspondiente.
- La función se ejecuta en infraestructura administrada.
- El código procesa método, headers, query, body y reglas de negocio.
- La función responde con un estado HTTP, headers y cuerpo de respuesta.[cite:2]
En Node.js moderno, Firebase expone esta capacidad mediante onRequest desde firebase-functions/v2/https.[cite:2]
Flujo de ejecución¶
En una HTTP Function, el flujo depende del diseño del endpoint, pero normalmente sigue este orden:
- recepción de la solicitud;
- lectura de método HTTP;
- validación de origen y headers;
- validación de parámetros o body;
- autenticación y autorización si aplica;
- ejecución de lógica de negocio;
- construcción de respuesta;
- finalización explícita con
send(),json(),redirect()oend().
La documentación advierte que una HTTP Function debe terminar explícitamente la respuesta. Si no se usa send(), redirect() o end(), la función puede seguir ejecutándose y terminar forzada por el sistema.[cite:2]
Métodos HTTP¶
Los métodos HTTP no son simples etiquetas. Comunican intención semántica y ayudan a diseñar APIs limpias.
GET¶
GET se utiliza para recuperar información. Debe ser idempotente y, en la práctica, no debería alterar el estado del sistema. En una aplicación Firebase, un GET puede servir para consultar disponibilidad, obtener un recurso, devolver configuración calculada o consultar un resumen generado por backend.
POST¶
POST se usa para crear recursos o ejecutar operaciones que no encajan en lectura simple. Es el método típico para registrar acciones, generar documentos, disparar integraciones o enviar formularios complejos.
PUT¶
PUT se usa para reemplazar completamente un recurso o una representación. En diseños serverless no siempre se utiliza de forma estricta, pero conserva valor cuando se desea semántica REST clara.
PATCH¶
Aunque la página principal de HTTP events destaca GET, POST, PUT, DELETE y OPTIONS, una API profesional suele contemplar también PATCH cuando quiere expresar una actualización parcial. El criterio aquí debe ser coherencia arquitectónica con el resto del sistema.
DELETE¶
DELETE representa eliminación lógica o física de recursos. En aplicaciones reales conviene ser prudente: muchas veces el backend no elimina de forma irreversible, sino que marca estados de archivado, revocación o soft delete.
Parámetros¶
Los parámetros se pueden recibir de varias maneras según el diseño de la ruta. Cuando se usa una app Express dentro de una HTTP Function, se pueden definir rutas como /:id, y entonces req.params.id representa el identificador solicitado.[cite:2]
Query Strings¶
La documentación oficial muestra cómo leer valores desde req.query. Por ejemplo, una función puede tomar format desde la URL para decidir cómo formatear una fecha o cómo ajustar un reporte.[cite:2]
Los query strings son útiles cuando:
- se desea filtrar resultados;
- ordenar una consulta;
- aplicar paginación;
- pasar opciones ligeras de lectura;
- expresar parámetros opcionales.
Body¶
El body representa el contenido principal de la solicitud, especialmente en POST, PUT y PATCH. La documentación muestra ejemplos en los que el servidor intenta leer format también desde req.body.[cite:2]
En backend profesional, el body debe validarse siempre. Nunca debe asumirse que el cliente enviará la estructura correcta.
Headers¶
Los headers cumplen varias funciones:
- transportar tokens de autenticación;
- negociar formato de respuesta;
- indicar tipo de contenido;
- propagar trazas o identificadores de solicitud;
- comunicar políticas de caché o CORS.
Una HTTP Function permite total flexibilidad sobre headers, lo que la hace especialmente adecuada para integraciones con clientes no Firebase o con servicios externos.
Códigos de respuesta HTTP¶
Una API profesional debe usar códigos de estado con intención. Algunos de los más comunes:
200 OK: operación exitosa.201 Created: recurso creado correctamente.204 No Content: operación exitosa sin cuerpo de respuesta.400 Bad Request: datos inválidos.401 Unauthorized: falta autenticación válida.403 Forbidden: el usuario no tiene permiso.404 Not Found: recurso inexistente.409 Conflict: conflicto de estado.422 Unprocessable Entity: estructura válida pero semántica inválida.500 Internal Server Error: fallo interno inesperado.
Usar bien estos códigos mejora depuración, observabilidad y experiencia de integración.
Manejo de errores¶
En HTTP Functions, el desarrollador controla el contrato de error. Eso aporta flexibilidad, pero también responsabilidad. Una práctica madura consiste en devolver objetos JSON consistentes, por ejemplo:
{
"error": {
"code": "INVALID_ARGUMENT",
"message": "El campo email es obligatorio",
"details": {
"field": "email"
}
}
}
Si la API será consumida por múltiples clientes, este contrato debe documentarse y mantenerse estable.
JSON¶
JSON es el formato natural para la mayoría de HTTP Functions porque encaja bien con frontend web, móvil y sistemas externos. También es el formato base esperado por muchos flujos modernos de integración.
CORS¶
La documentación oficial aclara que las HTTP Functions v2 no traen CORS habilitado por defecto. Si una función recibe una solicitud cross-origin sin política CORS configurada, el navegador la bloqueará.[cite:2] Para resolverlo, onRequest permite establecer la opción cors con true, con una lista de dominios, con expresiones regulares o mantenerla desactivada.[cite:2]
Arquitectónicamente, esto importa mucho. Una API pública o consumida desde varios frontends necesita una política CORS deliberada. Abrir cors: true puede ser práctico durante desarrollo, pero en producción suele ser preferible restringir orígenes.
Middleware¶
La página oficial muestra que una HTTP Function puede envolver una app Express completa y exponerla como una sola Cloud Function mediante onRequest(app).[cite:2] Esto permite usar middleware para autenticación, logging, normalización de errores, rate limiting lógico, parsing y agrupación de rutas.
Esta capacidad vuelve a las HTTP Functions especialmente atractivas cuando:
- se desea una mini API REST;
- se necesita compartir middleware;
- el equipo ya conoce Express;
- hay varios endpoints relacionados;
- se quiere una capa HTTP más flexible.
Seguridad básica¶
La seguridad básica de una HTTP Function incluye, como mínimo:
- validar método permitido;
- validar origen y CORS;
- validar tipo de contenido;
- autenticar al solicitante si el recurso no es público;
- autorizar según roles o permisos;
- sanear datos de entrada;
- limitar la superficie de respuesta;
- no exponer detalles internos en errores.
Una HTTP Function no recibe automáticamente el mismo nivel de mediación integrada que una callable. Por eso es más flexible, pero también exige más disciplina del lado del backend.
Callable Functions¶
¿Qué es una Callable Function?¶
Una Callable Function es una función HTTPS diseñada para ser invocada directamente desde una app Firebase mediante los SDKs cliente. La documentación oficial explica que las callable son similares, pero no idénticas, a las HTTP Functions.[cite:1]
En lugar de construir manualmente una solicitud HTTP genérica, el cliente usa el SDK y llama a la función por nombre. Firebase se encarga del protocolo, de incluir ciertos tokens disponibles y de validar parte de la solicitud automáticamente.[cite:1]
Diferencias respecto a HTTP Functions¶
La documentación resume varias diferencias clave:
- los tokens de Authentication, FCM y App Check, cuando están disponibles, se incluyen automáticamente en la solicitud;[cite:1]
- el trigger deserializa automáticamente el body;
- la plataforma valida tokens de autenticación automáticamente;[cite:1]
- el contrato de errores se basa en
HttpsError, que exponecode,messageydetailsal cliente de manera consistente.[cite:1]
En términos arquitectónicos, la Callable Function está optimizada para comunicación app ↔ backend dentro del ecosistema Firebase.
Comunicación mediante Firebase SDK¶
La llamada desde cliente se realiza con httpsCallable. En Web modular, por ejemplo, se obtiene una referencia al SDK Functions y luego se llama a la función por nombre.[cite:1]
Esta forma de comunicación tiene varias ventajas:
- reduce código de transporte en cliente;
- simplifica autenticación integrada;
- unifica serialización y manejo de errores;
- mejora la experiencia del desarrollador cuando el frontend ya usa Firebase.
Contexto del usuario¶
Una de las mayores fortalezas de las callable es el contexto del usuario. La documentación muestra que request.auth contiene información de autenticación como uid y claims del token cuando el usuario está autenticado.[cite:1]
Eso permite diseñar funciones donde el backend entiende inmediatamente quién llama, sin requerir que el frontend envíe manualmente datos que no deberían confiarse al cliente.
Validación automática¶
La plataforma valida tokens y deserializa el request body automáticamente.[cite:1] Esto no elimina la necesidad de validar los datos de negocio, pero sí reduce la carga de validación de transporte.
En otras palabras, la callable no evita que el backend deba revisar tipos, permisos o consistencia, pero sí elimina parte del trabajo repetitivo propio del protocolo.
Autenticación integrada¶
La autenticación integrada es quizá la diferencia más importante para muchos proyectos Firebase. Si el cliente ya utiliza Firebase Authentication, una callable puede aprovechar ese estado sin que el frontend tenga que construir una cabecera Authorization manual ni un flujo HTTP personalizado.[cite:1]
Eso la vuelve ideal para operaciones donde:
- el usuario ya inició sesión;
- la app web o móvil consume lógica interna;
- el endpoint no está pensado como API pública general;
- la autorización depende del usuario autenticado.
Manejo de errores¶
La documentación oficial indica que, para devolver errores útiles al cliente, la función debe lanzar HttpsError. Si se lanza cualquier otro error, el cliente recibirá un error internal genérico.[cite:1]
Esto es muy importante en arquitectura profesional. Obliga a diseñar errores intencionales y previsibles. Por ejemplo:
invalid-argumentpara datos inválidos;failed-preconditionpara estado no permitido;permission-deniedpara falta de autorización;unauthenticatedcuando falta identidad;internalsolo para errores no controlados.
Respuestas¶
Las callable deben devolver valores serializables a JSON. La documentación muestra ejemplos donde la función retorna objetos simples y el cliente los recibe ya estructurados.[cite:1]
Esto promueve un contrato de respuesta claro y sencillo. No se trabaja tanto en términos de códigos HTTP explícitos, sino de resultado o error estructurado del protocolo callable.
Casos de uso¶
Las callable encajan especialmente bien cuando:
- una app Firebase necesita ejecutar una operación interna protegida;
- la autorización depende del usuario autenticado;
- se desea aprovechar App Check y tokens integrados;
- el frontend y el backend pertenecen al mismo sistema;
- no se necesita exponer un endpoint REST genérico a terceros.
Ejemplos paso a paso¶
Elegir lenguaje: JavaScript moderno o TypeScript¶
Antes de escribir funciones conviene decidir el lenguaje. Ambos enfoques son válidos.
JavaScript moderno conviene cuando:
- el proyecto es pequeño o mediano;
- el equipo busca rapidez inicial;
- se están enseñando fundamentos;
- se quiere reducir complejidad de toolchain.
TypeScript conviene cuando:
- habrá muchas funciones y módulos;
- se requiere tipado fuerte para contratos de entrada y salida;
- el equipo trabaja con dominios complejos;
- se busca reducir errores de integración;
- se pretende escalar el backend de forma sostenida.
Para este manual se utilizarán ambos cuando aporte valor didáctico, indicando claramente la intención arquitectónica.
Ejemplo 1: HTTP Function para consumir una API externa¶
Este ejemplo es apropiado como HTTP Function porque representa un endpoint backend clásico que puede ser invocado por un frontend web, una herramienta administrativa o incluso un sistema externo. Además, necesita control explícito de método, query string, status code y CORS.[cite:2]
JavaScript moderno¶
import { onRequest } from "firebase-functions/v2/https";
export const consultarClima = onRequest(
{
region: "us-central1",
cors: ["https://tu-dominio.com"],
timeoutSeconds: 60,
},
async (req, res) => {
if (req.method !== "GET") {
return res.status(405).json({
error: { code: "METHOD_NOT_ALLOWED", message: "Usa GET" },
});
}
const ciudad = req.query.ciudad;
if (!ciudad || typeof ciudad !== "string") {
return res.status(400).json({
error: { code: "INVALID_ARGUMENT", message: "Falta ciudad" },
});
}
try {
const response = await fetch(`https://api.example.com/weather?city=${encodeURIComponent(ciudad)}`);
if (!response.ok) {
return res.status(502).json({
error: { code: "UPSTREAM_ERROR", message: "La API externa falló" },
});
}
const data = await response.json();
return res.status(200).json({ ciudad, clima: data });
} catch (error) {
return res.status(500).json({
error: { code: "INTERNAL", message: "Error interno" },
});
}
}
);
Qué ocurre internamente¶
- El navegador o cliente hace un GET a la URL de la función.
- Cloud Functions enruta la solicitud al servicio de la función.[cite:2]
- El código valida el método.
- Lee
req.query.ciudad. - Llama una API externa.
- Normaliza la respuesta.
- Devuelve JSON y finaliza correctamente con
res.status().json().[cite:2]
Ejemplo 2: Callable Function para enviar correo de bienvenida¶
Este ejemplo conviene como callable porque será invocado desde la app oficial del libro inmediatamente después de ciertas operaciones autenticadas. El backend necesita conocer el usuario autenticado y no tiene sentido exponer la operación como API pública general.[cite:1]
TypeScript¶
import { onCall, HttpsError } from "firebase-functions/v2/https";
interface WelcomeRequest {
fullName: string;
}
interface WelcomeResponse {
ok: boolean;
message: string;
}
export const enviarCorreoBienvenida = onCall<WelcomeRequest>(async (request): Promise<WelcomeResponse> => {
if (!request.auth) {
throw new HttpsError("unauthenticated", "Debes iniciar sesión");
}
const { fullName } = request.data;
if (!fullName || typeof fullName !== "string") {
throw new HttpsError("invalid-argument", "El nombre completo es obligatorio");
}
// Aquí iría la integración real con el proveedor de correo.
return {
ok: true,
message: `Correo de bienvenida preparado para ${fullName}`,
};
});
Qué ocurre internamente¶
- La app llama a la función con
httpsCallable.[cite:1] - El SDK adjunta tokens disponibles, como Authentication y App Check.[cite:1]
- La plataforma valida esos tokens automáticamente.[cite:1]
- La función recibe
request.datayrequest.authya preparados.[cite:1] - La lógica valida datos y procesa el caso de negocio.
- Devuelve un objeto serializable a JSON.[cite:1]
- El SDK cliente entrega el resultado ya estructurado.
Ejemplo 3: Callable Function para validar permisos antes de registrar información¶
Este caso también encaja mejor como callable porque la operación depende directamente del usuario autenticado y de sus privilegios sobre el sistema.
import { onCall, HttpsError } from "firebase-functions/v2/https";
export const validarRegistroAcademico = onCall(async (request) => {
if (!request.auth) {
throw new HttpsError("unauthenticated", "Usuario no autenticado");
}
const role = request.auth.token.role;
if (role !== "admin" && role !== "coordinador") {
throw new HttpsError("permission-denied", "No tienes permisos suficientes");
}
const { alumnoId, periodo } = request.data ?? {};
if (!alumnoId || !periodo) {
throw new HttpsError("invalid-argument", "Faltan datos requeridos");
}
return {
ok: true,
message: "Validación completada",
};
});
Ejemplo 4: HTTP Function para generar una credencial digital o PDF¶
Este ejemplo puede justificarse como HTTP Function cuando se necesita una URL backend que genere un documento o archivo consumible desde distintos clientes, incluso fuera del SDK de Firebase. También es apropiado cuando el resultado puede ser un binario, una descarga o una integración desde Hosting vía rewrite hacia Functions.[cite:2]
import { onRequest } from "firebase-functions/v2/https";
export const generarCredencial = onRequest(
{ cors: ["https://tu-dominio.com"], timeoutSeconds: 300 },
async (req, res) => {
if (req.method !== "POST") {
return res.status(405).json({ error: { code: "METHOD_NOT_ALLOWED", message: "Usa POST" } });
}
const { userId } = req.body ?? {};
if (!userId) {
return res.status(400).json({ error: { code: "INVALID_ARGUMENT", message: "userId es obligatorio" } });
}
// Aquí se generaría el PDF o la credencial.
return res.status(200).json({
ok: true,
message: "Credencial generada correctamente",
fileUrl: `https://storage.example.com/credenciales/${userId}.pdf`,
});
}
);
Ejemplo 5: Cliente Web para Callable Function¶
import { initializeApp } from "firebase/app";
import { getFunctions, httpsCallable } from "firebase/functions";
const app = initializeApp(firebaseConfig);
const functions = getFunctions(app, "us-central1");
const enviarCorreoBienvenida = httpsCallable(functions, "enviarCorreoBienvenida");
async function ejecutar() {
try {
const result = await enviarCorreoBienvenida({ fullName: "Ana Torres" });
console.log(result.data);
} catch (error: any) {
console.error(error.code, error.message, error.details);
}
}
La documentación oficial recomienda alinear la región de la función con la configuración del SDK cliente para reducir latencia.[cite:1]
Comparaciones técnicas¶
HTTP vs Callable¶
| Criterio | HTTP Function | Callable Function |
|---|---|---|
| Forma de consumo | URL HTTP directa [cite:2] | Firebase SDK o protocolo callable [cite:1] |
| Control de método | Total, basado en HTTP [cite:2] | No orientada a múltiples métodos HTTP explícitos |
| CORS | Debe configurarse deliberadamente; por defecto no está activo [cite:2] | Viene configurado para permitir solicitudes cross-origin por defecto, con posibilidad de restringirlo [cite:1] |
| Autenticación | El desarrollador la implementa | Tokens disponibles se incluyen automáticamente [cite:1] |
| Validación de transporte | Manual | Body deserializado y tokens validados por la plataforma [cite:1] |
| Contrato de errores | Basado en códigos y cuerpo HTTP | Basado en HttpsError con code, message, details [cite:1] |
| API pública | Muy adecuada | Menos adecuada |
| Cliente no Firebase | Muy adecuada | Requiere protocolo específico [cite:1] |
| Integración app Firebase | Buena | Excelente |
Ventajas¶
HTTP Functions
- Máxima flexibilidad de protocolo.
- Naturales para APIs REST, webhooks, integraciones externas y descargas.
- Compatibles con Express y middleware.[cite:2]
- Control explícito de métodos, headers y status codes.
Callable Functions
- Integración directa con Firebase SDK.[cite:1]
- Inclusión automática de tokens de Authentication, FCM y App Check cuando están disponibles.[cite:1]
- Manejo de errores más uniforme para cliente Firebase.[cite:1]
- Menor fricción para operaciones internas de la app.
Limitaciones¶
HTTP Functions
- Exigen más trabajo manual de autenticación y validación.
- Obligan a pensar en CORS y contrato HTTP con más detalle.[cite:2]
- Pueden derivar en APIs inconsistentes si no se estandarizan.
Callable Functions
- Son menos universales como API pública.
- Requieren SDK cliente compatible o implementación del protocolo específico.[cite:1]
- No sustituyen una API HTTP general cuando se integran terceros diversos.
Rendimiento¶
En rendimiento, la principal diferencia no está tanto en el runtime de Cloud Functions v2, sino en la complejidad de transporte y el patrón de consumo. Callable reduce trabajo del cliente dentro del ecosistema Firebase. HTTP ofrece más libertad, pero puede requerir más lógica en el frontend y más negociación de transporte.
La documentación también recuerda que la distancia entre cliente y región de la función afecta latencia, especialmente en callable. Por eso recomienda alinear la ubicación del SDK con la región elegida para la función.[cite:1]
Seguridad¶
En seguridad, Callable tiene ventaja ergonómica en apps Firebase porque puede aprovechar automáticamente tokens y App Check. HTTP, en cambio, ofrece un lienzo más abierto: eso es potente, pero exige diseñar manualmente más salvaguardas.[cite:1][cite:2]
Costos¶
Los costos dependen del tiempo de ejecución, memoria, CPU, concurrencia y volumen de llamadas, no únicamente del tipo HTTP o Callable. Sin embargo, una arquitectura mal diseñada puede encarecerse si expone operaciones demasiado frecuentes como llamadas serverless cuando parte de esa lógica podría resolverse en cliente o en reglas bien diseñadas.
Escalabilidad¶
Ambos modelos heredan la escalabilidad de Cloud Functions v2. La diferencia práctica está en el patrón de uso. Si la función será consumida por múltiples clientes, terceros, webhooks o integraciones heterogéneas, HTTP suele escalar mejor como contrato universal. Si la lógica es interna a la app Firebase, Callable escala bien en complejidad de desarrollo y mantenimiento.
¿Cuándo utilizar cada una?¶
Usa HTTP Function cuando:
- necesitas una API REST o شبه REST;
- vas a recibir webhooks;
- quieres exponer URLs a terceros;
- requieres control explícito de métodos, headers y status codes;
- necesitas servir archivos o respuestas especiales;
- integrarás la función con Hosting mediante rewrites.[cite:2]
Usa Callable Function cuando:
- el cliente principal es una app Firebase;
- el usuario ya está autenticado;
- la operación es interna del sistema;
- quieres reducir código cliente de autenticación y transporte;
- te beneficia el contrato estándar de
HttpsError.[cite:1]
Integración¶
Firestore¶
Tanto HTTP como Callable pueden leer y escribir Firestore desde el backend. En el proyecto del libro esto será útil para registrar actividad, consultar metadatos, verificar estados y producir documentos derivados.
Authentication¶
Callable sobresale cuando la autorización depende directamente del usuario autenticado, porque request.auth llega integrada desde el SDK y validada por la plataforma.[cite:1] HTTP también puede trabajar con Authentication, pero normalmente exige procesar tokens de forma más explícita.
Cloud Storage¶
Ambos enfoques pueden integrarse con Storage. Una HTTP Function puede generar una URL firmada o iniciar un proceso documental. Una Callable puede lanzar una operación interna protegida que derive en generación de archivo o transformación.
APIs externas¶
Las HTTP Functions suelen ser la opción más natural cuando la función se comporta como adaptador o proxy hacia una API externa. Permiten mayor control del contrato HTTP y de la respuesta.
Frontend¶
Para frontend Firebase, las Callable ofrecen una experiencia muy fluida. Para frontend universal, dashboards administrativos externos o integraciones no acopladas al SDK, las HTTP Functions suelen ser mejores.
Casos reales¶
Envío de correos¶
Mejor opción habitual: Callable Function cuando el correo se dispara por una acción de usuario autenticado dentro de la aplicación, por ejemplo un alta, una invitación o una confirmación interna. Se aprovecha request.auth y se evita exponer públicamente la operación.[cite:1]
Generación de PDFs¶
Puede ser HTTP o Callable, según el patrón de consumo.
- Callable si la app autenticada pide generar el documento como operación interna.
- HTTP si el resultado se va a descargar desde una URL, integrarse con Hosting o consumirse desde distintos clientes.
Validación de formularios¶
Mejor opción habitual: Callable Function cuando la validación depende del usuario, de claims o de lógica interna del sistema. La autenticación integrada simplifica el diseño.[cite:1]
Procesamiento de pagos¶
Mejor opción habitual: HTTP Function cuando se requiere interoperar con webhooks de pasarela o exponer endpoints controlados para proveedores externos. Un sistema de pagos suele necesitar HTTP estándar.
Consumo de APIs externas¶
Mejor opción habitual: HTTP Function si se desea una capa intermedia reutilizable y desacoplada del SDK. Callable también puede servir cuando la integración es puramente interna y asociada a una acción autenticada.
Automatización de procesos¶
La automatización puede entrar por ambos caminos. Si el disparador es una acción de usuario desde la app, Callable es muy cómoda. Si el proceso debe quedar expuesto como endpoint o interfaz de integración, HTTP resulta más adecuada.
Proyecto transversal del libro¶
Dentro del proyecto oficial del manual, una propuesta inicial de uso sería:
- Generar credencial digital: HTTP Function si la salida será un documento descargable o integrable por URL; Callable si el proceso se invoca internamente y devuelve metadatos.
- Enviar correo de bienvenida: Callable Function, porque depende del usuario autenticado y de una acción interna de la app.[cite:1]
- Validar permisos antes de registrar información: Callable Function, porque el contexto del usuario es central.[cite:1]
- Consumir una API externa: HTTP Function, si se diseña como gateway reutilizable.
- Generar un PDF: HTTP o Callable según patrón de consumo, aunque HTTP suele ser muy natural para descargas.
- Registrar actividad del usuario: Callable Function cuando nace directamente desde interacción autenticada.
Buenas prácticas¶
- Elegir el tipo de función por contrato y patrón de consumo, no por costumbre.
- Mantener funciones pequeñas, con responsabilidad única.
- Separar capa de transporte, validación y negocio.
- Centralizar utilidades de validación y autorización.
- En HTTP, definir una convención estable de errores y códigos de respuesta.
- En Callable, lanzar siempre
HttpsErrorpara errores esperados.[cite:1] - Restringir CORS en HTTP Functions cuando la API no sea pública.[cite:2]
- Alinear regiones entre cliente y función para reducir latencia.[cite:1][cite:2]
- Preferir TypeScript en proyectos de Functions que crecerán con muchos contratos y módulos.
- Aprovechar App Check para proteger endpoints, especialmente en callable.[cite:1]
- Usar Express en HTTP solo cuando realmente aporte valor; no envolver todo en middleware pesado por inercia.
- Registrar logs estructurados y no exponer mensajes internos al cliente.
Errores comunes¶
- Usar HTTP Function cuando una Callable resolvería mejor una operación interna autenticada.
- Usar Callable para una integración que realmente necesita un endpoint HTTP universal.
- No terminar la respuesta de una HTTP Function correctamente.[cite:2]
- Dejar CORS completamente abierto en producción sin justificación.[cite:2]
- Confiar en datos enviados por el cliente cuando
request.authya ofrece contexto verificable en callable.[cite:1] - Lanzar errores genéricos en callable en lugar de
HttpsError, perdiendo semántica para el cliente.[cite:1] - Mezclar demasiada lógica en una sola función y volverla difícil de probar y mantener.
- No alinear la región del SDK cliente con la región de la función, generando latencia innecesaria.[cite:1]
- Implementar una “API REST” sin convención clara de métodos, payloads y códigos.
Resumen¶
HTTP Functions y Callable Functions resuelven problemas cercanos, pero no idénticos. Las HTTP Functions son endpoints HTTP serverless de propósito general, ideales para APIs públicas, webhooks, descargas, integraciones externas y escenarios donde el desarrollador necesita control explícito sobre métodos, headers, CORS y códigos de respuesta.[cite:2]
Las Callable Functions, en cambio, están diseñadas para comunicación directa entre una app Firebase y el backend. El SDK cliente simplifica el transporte, adjunta automáticamente tokens cuando están disponibles, valida autenticación y entrega al desarrollador un contexto más integrado para operaciones internas del sistema.[cite:1]
La decisión correcta no depende de cuál sea “más poderosa”, sino de cuál encaja mejor con el contrato que el sistema necesita. Si el objetivo es construir una API universal y explícita, HTTP suele ser la opción natural. Si el objetivo es ejecutar operaciones internas autenticadas desde una app Firebase con menor fricción, Callable es normalmente la mejor elección.[cite:1][cite:2]
En el proyecto oficial del libro, ambas convivirán. Algunas operaciones como validaciones de permisos, envío de correos internos y registro de actividad encajan mejor como callable. Otras, como generación documental descargable, gateways hacia APIs externas o futuros webhooks, encajan mejor como HTTP Functions. Esta combinación refleja una arquitectura backend madura: no se elige una sola herramienta para todo, sino la adecuada para cada responsabilidad.
Conceptos clave¶
- HTTP Function.[cite:2]
- Callable Function.[cite:1]
onRequest.[cite:2]onCall.[cite:1]- CORS.[cite:2]
HttpsError.[cite:1]request.auth.[cite:1]- Query string.[cite:2]
- Request body.[cite:2]
- Headers.
- Middleware Express.[cite:2]
- Firebase SDK for Functions.[cite:1]
- App Check.[cite:1]
- JSON serializable response.[cite:1]
- Status code HTTP.[cite:2]
Preguntas de repaso¶
- ¿Qué es una HTTP Function y qué la diferencia de una Callable Function?[cite:1][cite:2]
- ¿Qué tipo de método de invocación utiliza cada una?
- ¿Qué ventajas aporta
request.authdentro de una Callable Function?[cite:1] - ¿Por qué una HTTP Function requiere mayor atención a CORS?[cite:2]
- ¿Qué sucede si una Callable Function lanza un error genérico en lugar de
HttpsError?[cite:1] - ¿Cuándo conviene usar Express dentro de una HTTP Function?[cite:2]
- ¿Por qué una Callable Function suele ser mejor para operaciones internas de una app Firebase?[cite:1]
- ¿Qué casos del proyecto del libro encajan mejor en HTTP y cuáles en Callable?
- ¿Cómo influyen región, latencia y patrón de consumo en la decisión arquitectónica?[cite:1][cite:2]
- ¿Cuándo conviene TypeScript frente a JavaScript moderno en un proyecto de Functions?
Ejercicios prácticos¶
- Diseña una tabla de decisión propia para clasificar operaciones del proyecto entre HTTP y Callable.
- Implementa una HTTP Function v2 que reciba un
GETcon query string y devuelva JSON normalizado.[cite:2] - Implementa una Callable Function v2 que exija autenticación y devuelva un objeto con resultado de validación.[cite:1]
- Crea una convención de errores JSON para HTTP Functions y compárala con el modelo
HttpsError.[cite:1] - Diseña una mini API documental con Express montada sobre una sola HTTP Function.[cite:2]
- Diseña una Callable Function para registrar actividad del usuario autenticado en Firestore.[cite:1]
- Explica qué CORS habilitarías en una HTTP Function interna, una pública y una solo para tu dominio.[cite:2]
- Reescribe uno de los ejemplos del capítulo en TypeScript añadiendo interfaces de entrada y salida.
- Propón una estructura modular de carpetas para Functions que separe transporte, validación, dominio e integraciones.
- Analiza qué endpoint del proyecto debería quedar detrás de Hosting con rewrites hacia HTTP Functions.[cite:2]
Bibliografía y referencias oficiales¶
- Call functions from your app | Cloud Functions for Firebase: https://firebase.google.com/docs/functions/callable [cite:1]
- Call functions via HTTP requests | Cloud Functions for Firebase: https://firebase.google.com/docs/functions/http-events [cite:2]