Para probar un Supabase Database Webhook en localhost, utilice host.docker.internal cuando Supabase y su receptor se ejecutan en su máquina, o utilizar un túnel HTTPS público cuando un proyecto hospedado Supabase debe llamar a su aplicación local. La distinción importa: Postgres local se ejecuta en Docker, donde localhost significa el contenedor de bases de datos, mientras hospedado Supabase necesita una URL accesible a Internet.
Qué Supabase Database Webhooks enviar
Database Webhooks reacciona a Postgres INSERT, UPDATE, y DELETE operaciones en una tabla seleccionada. Supabase los describe como un envoltorio asincrónico alrededor de los desencadenantes usando el pg_net extensión. La transacción que cambia la fila no espera que su receptor termine su lógica de negocio, lo que reduce el acoplamiento, pero también significa que el receptor debe ser observable y desconocido.
La carga útil JSON identifica la operación, esquema y tabla e incluye datos de fila. Para insertar y actualizar, record contiene la nueva fila. Para actualizaciones y eliminaciones, old_record proporciona la fila anterior donde está disponible. Construir controladores alrededor del sobre documentado en lugar de tratar cada solicitud como sólo un objeto de fila.
Montaje local versus proyecto alojado
Supabase local a una aplicación local: utilice el host Docker
Cuando corres supabase start, Postgres está dentro de un contenedor. Una URL de Webhook como http://localhost:3000/api/supabase-db-hook los bucles de vuelta en ese contenedor y generalmente falla. Supabase oficial Database Webhooks documentación dice que el objetivo host.docker.internal:
http://host.docker.internal:3000/api/supabase-db-hook
Esta ruta no requiere un túnel público. En los motores Linux donde ese nombre de host no está disponible, utilice el mapeo de host-gateway soportado por su configuración Docker o la dirección LAN de su máquina, como sugieren los puntos Supabase. Confirme desde un contenedor, no sólo desde el navegador host.
Hosted Supabase a una aplicación local: use HTTPS
Una base de datos en la nube no puede resolver el nombre de host Docker de su computadora portátil o dirección de vuelta privada. Iniciar la aplicación local y ejecutar npx portpreview 3000, luego configure:
https://your-subdomain.portpreview.dev/api/supabase-db-hook
Utilice un proyecto de desarrollo dedicado o una tabla de bajo riesgo. Un webhook de nube puede incluir datos de fila real, por lo que exponer una tabla de producción a una URL de desarrollo temporal es generalmente una estrategia de prueba deficiente.
Crear un receptor que valide un secreto compartido
A diferencia de los proveedores que definen un encabezado HMAC obligatorio, un Database Webhook es una solicitud HTTP configurable. Protege el endpoint con un encabezado secreto que controlas y configuras el mismo encabezado en el webhook. TLS lo protege en tránsito; una comparación de tiempo constante evita filtrar el tiempo de prefijo secreto a través de su aplicación.
// app/api/supabase-db-hook/route.ts
import crypto from 'node:crypto';
function safeEqual(a: string, b: string) {
const left = Buffer.from(a);
const right = Buffer.from(b);
return left.length === right.length &&
crypto.timingSafeEqual(left, right);
}
export async function POST(request: Request) {
const supplied = request.headers.get('x-webhook-secret') ?? '';
const expected = process.env.SUPABASE_DB_WEBHOOK_SECRET ?? '';
if (!expected || !safeEqual(supplied, expected)) {
return new Response('unauthorized', { status: 401 });
}
const payload = await request.json();
if (!['INSERT', 'UPDATE', 'DELETE'].includes(payload.type)) {
return new Response('unsupported event', { status: 400 });
}
await recordDelivery(payload);
return new Response('accepted', { status: 200 });
}
Un encabezado compartido demuestra conocimiento del secreto pero no une criptográficamente ese secreto al cuerpo. Si se requiere evidencia de amortiguación a nivel de cuerpo, envíe el Database Webhook a un pequeño Edge Function de confianza que valida su propio secreto inbound, computa su HMAC elegido sobre un cuerpo canónico y lo envía al consumidor local o de producción. No inventes un X-Supabase-Signature suposición a menos que su propia capa de reenvío crea y lo verifica.
Configurar y activar un Webhook enfocado
- Elija una tabla de desarrollo y decida qué operaciones importan.
- Cree el Database Webhook en el panel Supabase bajo la base de datos → Webhooks, seleccionando el esquema, tabla y operaciones.
- Establecer la URL local Docker o la URL del túnel público descrita anteriormente.
- Añadir
Content-Type: application/jsony un azarX-Webhook-Secretvalor donde está disponible la configuración de encabezados webhook. - Comience el receptor e inserte una fila de prueba claramente etiquetada.
- Actualizar un campo, luego eliminar la fila, verificar todos los sobres seleccionados.
- Eliminar o desactivar el webhook de prueba antes de cambiar proyectos o cerrar el túnel.
Nombre de las filas de prueba para limpiar es determinista. No dispare una integración en toda la mesa en los registros de los clientes de producción simplemente para ver una solicitud llegar.
Interpretar INSERT, UPDATE y DELETE de forma segura
INSERT
Uso record como el estado recién insertado. Si el receptor crea un objeto correspondiente en otro lugar, almacena la clave principal de la tabla fuente como clave de idempotencia. Un evento de inserción se puede enviar de nuevo durante la repetición manual o el procesamiento de reingreso personalizado.
UPDATE
Compare record con old_record y actuar sólo en campos relevantes para la integración. Un webhook de actualización general puede disparar para los timetamps o metadatos no relacionados. Filtrar cambios de negocio no-op evita costosas llamadas de abajo.
DELETE
La fila eliminada está representada por datos anteriores en lugar de un registro actual. Hacer manipuladores de eliminación tolerantes a campos opcionales desaparecidos y decidir si la acción aguas abajo es la eliminación, archivo o revocación. Requisitos de auditoría de presto.
switch (payload.type) {
case 'INSERT':
await mirror.upsert(payload.record.id, payload.record);
break;
case 'UPDATE':
if (payload.old_record.status !== payload.record.status) {
await syncStatus(payload.record.id, payload.record.status);
}
break;
case 'DELETE':
await mirror.archive(payload.old_record.id);
break;
}
Confiabilidad de entrega es una preocupación de aplicación
Debido a que Database Webhooks son solicitudes de red asincrónicas, no trate la recepción como una transacción distribuida con el cambio de fila originario. Su lado remoto puede no estar disponible después de que Postgres se comprometa. Supervisar los resultados de solicitud y diseñar la reconciliación para cualquier cosa que no pueda perderse.
Para los flujos de trabajo de alto valor, una tabla de outbox es más fuerte: escribir un cambio de negocio y una fila de outbox en una transacción de base de datos, luego dejar a un trabajador entregar con contadores de reingreso explícitos, retroceso y manejo de letras muertas. Un Database Webhook puede notificar al trabajador, pero la reconciliación periódica todavía debe encontrar filas de outbox sin entrega.
Haga el receptor idempotent. Una clave útil combina esquema de fuente, tabla, operación, clave primaria y una versión de fila estable como updated_at; para garantías estrictas, agregue un evento inmutable UUID en una fila outbox. Evite escalar sólo la fila actual porque dos transiciones válidas pueden producir proyecciones similares.
Llamando a un Supabase local
Si el destino es un Edge Function servido por la pila Supabase local, el ejemplo documentado es:
http://host.docker.internal:54321/functions/v1/my-function-name
El funcionario Edge Functions guía de desarrollo usos supabase functions serve [function-name] para recargar caliente local. Edge Functions requiere verificación JWT por defecto. Para una función webhook que no puede suministrar un usuario JWT, configure esa función deliberadamente, por ejemplo con verify_jwt = false dentro supabase/config.toml, como se documenta en Configuración de funciones. Reemplazar la autenticación JWT con su cabeza secreta o cheque de firma; desactivar JWT solo hace la función pública.
Solución de problemas Supabase webhook localhost delivery
Conexión rechazada de la pila local
Reemplazamiento localhost con host.docker.internal, verificar la aplicación se une a una interfaz accesible desde Docker, y confirmar el puerto. En Linux, configura la resolución host-gateway o utiliza la IP host. Un servicio vinculado sólo a una interfaz inesperada puede rechazar el tráfico de contenedores.
El proyecto hospedado nunca llega a la ruta
Un proyecto hospedado necesita la URL del túnel público HTTPS, no el nombre de host Docker. Confirme que el túnel está en vivo y su URL incluye la ruta completa. Chequee DNS/TLS poniéndolo usted mismo.
La ruta regresa 401
Compare el nombre y el valor del encabezado configurados, observe el espacio blanco líder o rastreador, y reinicie la aplicación después de cambiar variables de entorno. Inicie si el encabezado existe, nunca su valor. Si un intermediario tira los encabezados personalizados, utilice un Authorization: Bearer ... encabezado y validarlo explícitamente.
La forma de la carga parece equivocada
Lograr sólo las claves de primer nivel, operación, esquema y mesa en desarrollo. Recuerde que DELETE utiliza datos de fila anteriores y UPDATE puede incluir ambas versiones. Validar contra los ejemplos oficiales de carga útil actuales antes de cambiar su parser.
La actualización de la base de datos tiene éxito pero falta trabajo corriente
Ese comportamiento es posible en un diseño asincrónico. Inspeccione los registros de solicitud webhook pg_net Diagnóstico disponible en su entorno, luego añadir reingreso o reconciliación en lugar de revertir una transacción comercial ya comprometida.
Lista de verificación de seguridad
- Utilice HTTPS para las pruebas alocal y rotar el secreto compartido temporal después.
- Envíe únicamente las columnas necesarias; evite exponer tablas sensibles o grandes cargas de producción.
- Validar un encabezado secreto antes de analizar o persistir el cuerpo.
- Aplicar POST solo enrutamiento, límites de tamaño de solicitud, controles de velocidad y registros redactados.
- Utilice configuraciones separadas local, estadificación y webhook de producción.
- Construir registros explícitos, idempotencia, monitoreo y reconciliación para eventos importantes.
- Desactivar URLs temporales de nube webhook cuando el túnel se cierra.
El fallo local más común es la dirección de red, no Postgres: llamadas locales-container utilizan host.docker.internal; las llamadas nubes usan un túnel público. Una vez que llegue el tráfico, trate la autenticación y las garantías de entrega como problemas de diseño separados. Examen seguridad del túnel local y patrones de confiabilidad webhook antes de conectar datos sensibles.
