Tous les articles
Événements d’insertion, de mise à jour et de suppression de lignes Postgres transmis d’une base Supabase à un endpoint webhook local sécurisé.
Supabasedatabase webhooksPostgreslocal development

Tester les Database Webhooks Supabase sur localhost

Pour tester un Supabase Database Webhook sur localhost, utilisez host.docker.internal lorsque Supabase et votre récepteur fonctionnent sur votre machine, ou utilisez un tunnel public HTTPS lorsqu'un projet Supabase hébergé doit appeler votre application locale. La distinction est importante: local Postgres fonctionne dans Docker, où localhost signifie le conteneur de base de données, alors que Supabase hébergé a besoin d'une URL accessible sur Internet.

Ce que Supabase Database Webhooks envoie

Database Webhooks réagit à Postgres INSERT, UPDATEet DELETE les opérations sur une table sélectionnée. Supabase les décrit comme un enrouleur asynchrone autour des déclencheurs en utilisant le pg_net prolongation. La transaction qui change la ligne n'attend pas que votre récepteur termine sa logique d'affaires, ce qui réduit le couplage, mais signifie aussi que le récepteur doit être observable et averti de défaillance.

La charge utile JSON identifie l'opération, le schéma et le tableau et inclut les données de ligne. Pour les insertions et mises à jour, record contient la nouvelle ligne. Pour les mises à jour et les suppressions, old_record fournit la ligne précédente lorsque disponible. Construisez des gestionnaires autour de l'enveloppe documentée plutôt que de traiter chaque requête comme un objet de ligne.

Pile locale versus projet hébergé

Supabase local vers une application locale : utilisez l'hôte Docker

Quand tu cours supabase start, Postgres est à l'intérieur d'un conteneur. Une URL webhook comme http://localhost:3000/api/supabase-db-hook retourne dans ce conteneur et échoue habituellement. Le fonctionnaire de Supabase Database Webhooks documentation indique de cibler host.docker.internal:

http://host.docker.internal:3000/api/supabase-db-hook

Cette route ne nécessite pas de tunnel public. Sur les moteurs Linux où ce nom d'hôte n'est pas disponible, utilisez la cartographie host-gateway prise en charge par votre configuration Docker ou l'adresse LAN de votre machine, comme le suggèrent les documents Supabase. Confirmer à partir d'un conteneur, pas seulement à partir du navigateur hôte.

Hôté Supabase à une application locale : utilisez HTTPS

Une base de données cloud ne peut pas résoudre le nom d'hôte Docker de votre ordinateur portable ou l'adresse de retour en boucle privée. Démarrez l'application locale et lancez npx portpreview 3000, puis configurer :

https://your-subdomain.portpreview.dev/api/supabase-db-hook

Utilisez un projet de développement dédié ou une table à faible risque. Un webhook cloud peut inclure des données en ligne réelles, donc exposer une table de production à une URL de développement temporaire est généralement une mauvaise stratégie de test.

Créer un récepteur qui valide un secret partagé

Contrairement aux fournisseurs qui définissent un en-tête HMAC obligatoire, un Database Webhook est une requête HTTP configurable. Protégez le paramètre avec un en-tête secret que vous contrôlez et configurez le même en-tête sur le webhook. TLS le protège en transit; une comparaison à temps constant évite les fuites de temps de préfixe secret à travers votre application.

// 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 en-tête partagé prouve la connaissance du secret, mais ne lie pas ce secret au corps. Si une preuve d'altération au niveau du corps est nécessaire, envoyez le Database Webhook à un petit Edge Function de confiance qui valide son propre secret d'entrée, calcule votre HMAC sur un corps d'entrée canonique, et le transmet au consommateur local ou de production. Ne pas inventer X-Supabase-Signature supposition à moins que votre propre couche de renvoi crée et vérifie.

Configurer et déclencher un webhook ciblé

  1. Choisissez une table de développement et décidez quelles opérations comptent.
  2. Créez le Database Webhook dans le tableau de bord Supabase sous Base de données → Webhooks, en sélectionnant le schéma, la table et les opérations.
  3. Définir l'URL locale Docker ou l'URL du tunnel public décrite ci-dessus.
  4. Ajouter Content-Type: application/json et au hasard X-Webhook-Secret valeur où la configuration d'en-tête webhook est disponible.
  5. Démarrez le récepteur et insérez une ligne de test clairement marquée.
  6. Mettre à jour un champ, puis supprimer la ligne, en vérifiant toutes les enveloppes sélectionnées.
  7. Supprimer ou désactiver le webhook de test avant de changer de projet ou de fermer le tunnel.

Nommez les lignes de test pour que le nettoyage soit déterministe. Ne tirez pas une intégration à l'échelle de la table dans les dossiers clients de production simplement pour voir une demande arriver.

Interpréter INSERT, UPDATE et DELETE en toute sécurité

INSERT

Utilisation record comme l'état nouvellement inséré. Si le récepteur crée un objet correspondant ailleurs, stockez la clé primaire de la table source comme clé d'idempotency. Un événement d'insertion peut être livré à nouveau lors d'un replay manuel ou d'un traitement de réessayer personnalisé.

UPDATE

Comparer record avec old_record et n'agir que dans des domaines pertinents à l'intégration. Une mise à jour générale du webhook peut déclencher des horodatages ou des métadonnées non liées. Le filtrage des changements d'affaires non-op empêche les appels en aval coûteux.

DELETE

La ligne supprimée est représentée par des données antérieures plutôt que par un enregistrement courant. Rendre les gestionnaires de suppression tolérants aux champs facultatifs manquants et décider si l'action en aval est la suppression, l'archivage ou la révocation. Préserver les exigences en matière de vérification.

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;
}

La fiabilité de la livraison est un problème d'application

Comme Database Webhooks sont des requêtes réseau asynchrones, ne traitez pas la réception comme une transaction distribuée avec le changement de ligne d'origine. Votre côté distant peut ne pas être disponible après les commits Postgres. Surveiller les résultats des demandes à l'étranger et le rapprochement de la conception pour tout ce qui ne peut être perdu.

Pour les workflows de grande valeur, une table de cases est plus forte : écrivez un changement d'entreprise et une ligne de cases dans une transaction de base de données, puis laissez un travailleur livrer avec des compteurs de réessayer explicites, backoff, et la gestion de lettres mortes. Un Database Webhook peut en informer le travailleur, mais le rapprochement périodique devrait encore trouver des lignes de boîte de réception non livrées.

Faites l'idémpotent du récepteur. Une clé utile combine schéma source, table, opération, clé primaire, et une version de ligne stable comme updated_at; pour des garanties strictes, ajouter un événement immuable UUID dans une ligne de messagerie. Évitez de hacher seulement la ligne actuelle parce que deux transitions valides peuvent produire des projections similaires.

Appel d'un Supabase Edge Function local

Si la destination est un Edge Function desservi par la pile locale Supabase, l'exemple documenté est :

http://host.docker.internal:54321/functions/v1/my-function-name

Le fonctionnaire Guide de développement Edge Functions Utilisations supabase functions serve [function-name] pour recharger localement. Edge Functions nécessite une vérification JWT par défaut. Pour une fonction webhook qui ne peut pas fournir un utilisateur JWT, configurer cette fonction délibérément, par exemple avec verify_jwt = false dans supabase/config.toml, comme indiqué dans Configuration de la fonction. Remplacer l'authentification JWT par votre en-tête secret ou vérification de signature ; désactiver JWT seul rend la fonction publique.

Dépannage Supabase webhook livraison locale

Connexion refusée de la pile locale

Remplacer localhost avec host.docker.internal, vérifier que l'application se lie à une interface accessible depuis Docker, et confirmer le port. Sur Linux, configurer la résolution host-gateway ou utiliser l'IP hôte. Un service lié uniquement à une interface inattendue peut encore rejeter le trafic de conteneurs.

Le projet hébergé n'a jamais atteint l'itinéraire

Un projet hébergé a besoin de l'URL publique du tunnel HTTPS, et non du nom d'hôte Docker. Confirmer que le tunnel est en direct et que son URL inclut l'itinéraire complet. Vérifiez DNS/TLS en vous y inscrivant.

L'itinéraire retourne 401

Comparer le nom et la valeur d'en-tête configurés, regarder pour diriger ou suivre l'espace blanc, et redémarrer l'application après avoir modifié les variables d'environnement. Logez si l'en-tête existe, jamais sa valeur. Si un intermédiaire enlève des en-têtes personnalisés, utilisez un Authorization: Bearer ... et validez-le explicitement.

La forme de la charge utile semble fausse

Enregistrez seulement les clés de haut niveau, l'opération, le schéma et la table dans le développement. Rappelez-vous que DELETE utilise des données de lignes précédentes et UPDATE peut inclure les deux versions. Valider en fonction des exemples de charge utile officielle avant de changer votre analyseur.

La mise à jour de la base de données réussit, mais il manque des travaux en aval

Ce comportement est possible dans un design asynchrone. Inspecter les journaux de requêtes webhook et pg_net diagnostics disponibles dans votre environnement, puis ajouter réessayer ou rapprochement plutôt que de revenir en arrière une transaction d'affaires déjà engagée.

Liste de contrôle pour la sécurité

  • Utilisez HTTPS pour les tests hébergés vers le local et faites pivoter le secret partagé temporaire après.
  • Envoyer seulement les colonnes nécessaires; éviter d'exposer des tables sensibles ou des charges utiles de production larges.
  • Valider un en-tête secret avant d'analyser ou de persister le corps.
  • Appliquer le routage POST uniquement, les limites de la taille des requêtes, les contrôles de tarifs et les journaux expurgés.
  • Utiliser des configurations locales, de mise en scène et de production différentes.
  • Établir des relevés explicites, des mesures d'urgence, de surveillance et de réconciliation pour les événements importants.
  • Désactiver les URL de cloud temporaire lorsque le tunnel se ferme.

Le bogue local le plus courant est l'adressage réseau, pas Postgres: les appels local-container utilisent host.docker.internal; les appels en nuage utilisent un tunnel public. Une fois le trafic arrivé, traiter les garanties d'authentification et de livraison comme des problèmes de conception distincts. Révision Sécurité des tunnels locaux et modèles de fiabilité webhook avant de connecter des données sensibles.

Questions fréquentes

Pourquoi un Supabase Database Webhook n'atteint-il pas localhost?
Local Supabase Postgres fonctionne dans Docker, donc localhost se réfère au conteneur. Utilisez host.docker.internal ou votre IP hôte. Un projet Supabase hébergé nécessite plutôt une URL publique du tunnel HTTPS.
Ai-je besoin d'un tunnel pour Supabase Database Webhooks local?
Pas lorsque les Supabase et le récepteur sont locaux; utilisez le routage d'hôte Docker. Vous avez besoin d'un tunnel lorsqu'un projet Supabase hébergé doit appeler une application fonctionnant sur votre ordinateur.
Supabase Database Webhooks sont-ils signés automatiquement?
Ne présumez pas un en-tête HMAC fournisseur. Configurer et valider un en-tête secret partagé. Si vous avez besoin d'une signature liée au corps, faites suivre par une fonction de confiance qui crée un HMAC votre récepteur vérifie.
Quelles données un Supabase Database Webhook envoie-t-il?
L'enveloppe JSON identifie INSERT, UPDATE ou DELETE plus le schéma et le tableau. Il comprend le nouvel enregistrement pour les insertions et les mises à jour et les données de ligne précédentes pour les mises à jour ou les suppressions lorsque disponibles.