Um ein Supabase Database Webhook auf localhost zu testen, verwenden Sie host.docker.internal wenn sowohl Supabase als auch Ihr Empfänger auf Ihrem Computer laufen oder einen öffentlichen HTTPS-Tunnel verwenden, wenn ein gehostetes Supabase-Projekt Ihre lokale App aufrufen muss. Die Unterscheidung ist wichtig: Lokales Postgres läuft in Docker, wo localhost bezeichnet den Datenbankcontainer, während gehostete Supabase eine internetfähige URL benötigt.
Was Supabase Database Webhooks senden
Database Webhooks reagiert auf Postgres INSERT, UPDATE, und DELETE Operationen auf einer ausgewählten Tabelle. Supabase beschreibt sie als asynchronen Wrapper um Trigger mit dem pg_net Verlängerung. Die Transaktion, die die Zeile ändert, wartet nicht darauf, dass Ihr Empfänger seine Geschäftslogik beendet, was die Kopplung reduziert, aber auch bedeutet, dass der Empfänger beobachtbar und ausfallsicher sein muss.
Die JSON Nutzlast identifiziert die Operation, das Schema und die Tabelle und enthält Zeilendaten. Für Einsätze und Updates, record enthält die neue Zeile. für Updates und Löschungen, old_record Angabe der vorherigen Zeile, sofern verfügbar. Erstellen Sie Handler um den dokumentierten Umschlag herum, anstatt jede Anfrage nur als Zeilenobjekt zu behandeln.
Lokaler Stack versus gehostetes Projekt
Lokales Supabase in einer lokalen App: Verwenden Sie den Docker-Host
Wenn Sie laufen supabase startPostgres befindet sich in einem Container. Eine Webhook-URL wie http://localhost:3000/api/supabase-db-hook Loops zurück in diesen Container und in der Regel fehlschlägt. Supabase offiziell Database Webhooks Dokumentation Sagt zum Ziel host.docker.internal:
http://host.docker.internal:3000/api/supabase-db-hook
Diese Route erfordert keinen öffentlichen Tunnel. Verwenden Sie auf Linux-Engines, bei denen dieser Hostname nicht verfügbar ist, das Host-Gateway-Mapping, das von Ihrem Docker-Setup oder der LAN-Adresse Ihres Computers unterstützt wird, wie es die Supabase-Dokumente vorschlagen. Bestätigen Sie aus einem Container, nicht nur aus dem Host-Browser.
Hostetes Supabase in einer lokalen App: Verwenden Sie HTTPS
Eine Cloud-Datenbank kann den Docker-Hostnamen oder die private Loopback-Adresse Ihres Laptops nicht auflösen. Starten Sie die lokale App und starten Sie npx portpreview 3000, dann konfigurieren:
https://your-subdomain.portpreview.dev/api/supabase-db-hook
Verwenden Sie ein dediziertes Entwicklungsprojekt oder eine Tabelle mit geringem Risiko. Ein Cloud-Webhook kann echte Zeilendaten enthalten, so dass das Aussetzen einer Produktionstabelle mit einer temporären Entwicklungs-URL normalerweise eine schlechte Teststrategie ist.
Erstellen Sie einen Empfänger, der ein gemeinsames Geheimnis validiert
Im Gegensatz zu Anbietern, die einen obligatorischen HMAC-Header definieren, ist ein Database Webhook eine konfigurierbare ausgehende HTTP-Anfrage. Schützen Sie den Endpunkt mit einem geheimen Header, den Sie steuern, und konfigurieren Sie denselben Header auf dem Webhook. TLS schützt es im Transit; Ein Vergleich mit konstanter Zeit vermeidet das Auslaufen eines geheimen Präfix-Timings durch Ihre Anwendung.
// 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 });
}
Ein gemeinsamer Header beweist die Kenntnis des Geheimnisses, bindet dieses Geheimnis jedoch nicht kryptographisch an den Körper. Wenn Manipulationsbeweise auf Körperebene erforderlich sind, senden Sie das Database Webhook an ein kleines vertrauenswürdiges Edge Function, das sein eigenes eingehendes Geheimnis validiert, Ihr gewähltes HMAC über einen kanonischen ausgehenden Körper berechnet und an den lokalen oder Produktionsverbraucher weiterleitet. Erfinden Sie nicht ein X-Supabase-Signature Annahme, es sei denn, Ihre eigene Weiterleitungsschicht erstellt und überprüft sie.
Konfigurieren und Auslösen eines fokussierten Webhooks
- Wählen Sie eine Entwicklungstabelle und entscheiden Sie, welche Operationen wichtig sind.
- Erstellen Sie das Database Webhook im Supabase-Dashboard unter Datenbank → Webhooks und wählen Sie Schema, Tabelle und Operationen aus.
- Legen Sie die lokale Docker-URL oder die oben beschriebene öffentliche Tunnel-URL fest.
- Addition
Content-Type: application/jsonund ein ZufallsprinzipX-Webhook-SecretWert, bei dem die Webhook-Header-Konfiguration verfügbar ist. - Starten Sie den Empfänger und fügen Sie eine eindeutig gekennzeichnete Testzeile ein.
- Aktualisieren Sie ein Feld, löschen Sie dann die Zeile und überprüfen Sie alle ausgewählten Umschläge.
- Entfernen oder Deaktivieren Sie den Test-Webhook, bevor Sie Projekte wechseln oder den Tunnel schließen.
Benennen Sie Testreihen, so dass die Bereinigung deterministisch ist. Zünden Sie keine tischweite Integration in die Produktionsdatensätze, nur um eine Anfrage zu sehen.
Interpretieren Sie INSERT, UPDATE und DELETE sicher
PPXTERM00038X
Verwendung record als neu eingefügter Zustand. Wenn der Empfänger ein entsprechendes Objekt an anderer Stelle erstellt, speichern Sie den Primärschlüssel der Quelltabelle als Idempotenzschlüssel. Ein Insert-Ereignis kann während der manuellen Wiederholung oder der benutzerdefinierten Wiederholungsverarbeitung erneut geliefert werden.
PPXTERM00039X
Vergleichen record mit old_record und handeln nur in für die Integration relevanten Bereichen. Ein allgemeiner Update-Webhook kann für Zeitstempel oder nicht verwandte Metadaten ausgelöst werden. Das Filtern von No-Op-Geschäftsänderungen verhindert teure Downstream-Anrufe.
DELETE
Die gelöschte Zeile wird durch frühere Daten anstelle eines aktuellen Datensatzes dargestellt. Machen Sie Lösch-Handler tolerant gegenüber fehlenden optionalen Feldern und entscheiden Sie, ob die nachgelagerte Aktion Löschen, Archivieren oder Widerrufen ist. Prüfungsanforderungen beibehalten.
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;
}
Lieferzuverlässigkeit ist ein Anwendungsproblem
Da Database Webhooks asynchrone Netzwerkanforderungen sind, behandeln Sie den Empfang nicht als verteilte Transaktion mit dem ursprünglichen Zeilenwechsel. Ihre Remote-Seite ist möglicherweise nach Postgres-Commits nicht verfügbar. Überwachen Sie Outbound-Request-Ergebnisse und entwerfen Sie den Abgleich für alles, was nicht verloren gehen kann.
Für hochwertige Workflows ist eine Outbox-Tabelle stärker: Schreiben Sie eine Geschäftsänderung und eine Outbox-Zeile in eine Datenbanktransaktion, und lassen Sie dann einen Mitarbeiter mit expliziten Wiederholungszählern, Backoff und Dead-Buchstaben-Handling liefern. Ein Database Webhook kann den Arbeiter benachrichtigen, aber ein periodischer Abgleich sollte immer noch nicht zugestellte Posteingangszeilen finden.
Machen Sie den Empfänger idempotent. Ein nützlicher Schlüssel kombiniert Quellschema, Tabelle, Operation, Primärschlüssel und eine stabile Zeilenversion wie updated_at; Für strenge Garantien fügen Sie ein unveränderliches Ereignis UUID in einer Posteingangszeile hinzu. Vermeiden Sie das Hashen nur der aktuellen Zeile, da zwei gültige Übergänge ähnliche Projektionen erzeugen können.
Aufruf eines lokalen Supabase Edge Function
Wenn das Ziel ein Edge Function ist, das vom lokalen Supabase-Stack bedient wird, lautet das dokumentierte Beispiel:
http://host.docker.internal:54321/functions/v1/my-function-name
Der Beamte Edge Functions Entwicklungsleitfaden Verwendung supabase functions serve [function-name] für lokales heißes Nachladen. Edge Functions erfordert standardmäßig eine JWT-Verifizierung. Für eine Webhook-Funktion, die einen Benutzer nicht mit JWT versorgen kann, konfigurieren Sie diese Funktion absichtlich, z. B. mit verify_jwt = false in supabase/config.toml, wie dokumentiert in FunktionskonfigurationErsetzen Sie die JWT-Authentifizierung durch Ihre Geheimkopf- oder Signaturprüfung; die Deaktivierung von JWT allein macht die Funktion öffentlich.
Fehlerbehebung Supabase webhook localhost Lieferung
Verbindung vom lokalen Stapel abgelehnt
Ersetzen localhost mit host.docker.internalÜberprüfen Sie, ob die App an eine von Docker erreichbare Schnittstelle bindet, und bestätigen Sie den Port. Auf Linux konfigurieren Sie die Host-Gateway-Auflösung oder verwenden Sie die Host-IP. Ein Dienst, der nur an eine unerwartete Schnittstelle gebunden ist, kann weiterhin Containerverkehr ablehnen.
Das gehostete Projekt erreicht nie die Route
Ein gehostetes Projekt benötigt die öffentliche HTTPS-Tunnel-URL, nicht den Hostnamen Docker. Bestätigen Sie, dass der Tunnel live ist und seine URL die komplette Route enthält. Überprüfen Sie DNS/TLS, indem Sie es selbst posten.
Die Route gibt 401 zurück
Vergleichen Sie den konfigurierten Header-Namen und -Wert, achten Sie auf führenden oder nachlaufenden Whitespace und starten Sie die App nach dem Ändern von Umgebungsvariablen neu. Loggen Sie, ob der Header existiert, niemals seinen Wert. Wenn ein Zwischenhändler benutzerdefinierte Header entfernt, verwenden Sie einen herkömmlichen Authorization: Bearer ... Header und validieren Sie es explizit.
Die Nutzlastform scheint falsch zu sein
Protokollieren Sie nur die Top-Level-Schlüssel, Operation, Schema und Tabelle in der Entwicklung. Denken Sie daran, dass DELETE frühere Zeilendaten verwendet und UPDATE beide Versionen enthalten kann. Validieren Sie mit den aktuellen offiziellen Nutzlastbeispielen, bevor Sie Ihren Parser ändern.
Das Datenbank-Update ist erfolgreich, aber Downstream-Arbeiten fehlen
Dieses Verhalten ist in einem asynchronen Design möglich. Überprüfen Sie Webhook Request Logs und pg_net Diagnosen, die in Ihrer Umgebung verfügbar sind, fügen Sie dann Wiederholungen oder Abgleiche hinzu, anstatt eine bereits festgelegte Geschäftstransaktion zurückzusetzen.
Sicherheitscheckliste
- Verwenden Sie HTTPS für Hosted-to-Local-Tests und drehen Sie das temporäre gemeinsame Geheimnis danach.
- Senden Sie nur notwendige Spalten; vermeiden Sie das Aussetzen sensibler Tabellen oder breiter Produktionsnutzlasten.
- Validieren Sie einen geheimen Header, bevor Sie den Körper analysieren oder persistieren.
- Anwenden von POST-only Routing, Request-Größenlimits, Ratenkontrollen und bearbeiteten Protokollen.
- Verwenden Sie separate lokale, Staging- und Produktionswebhook-Konfigurationen.
- Bauen Sie explizite Wiederholungen, Idempotenz, Überwachung und Versöhnung für wichtige Ereignisse auf.
- Deaktivieren Sie temporäre Cloud-Webhook-URLs, wenn der Tunnel geschlossen wird.
Der häufigste lokale Fehler ist die Netzwerkadressierung, nicht Postgres: lokale Containeranrufe verwenden host.docker.internalCloud Calls nutzen einen öffentlichen Tunnel. Sobald der Datenverkehr eintrifft, behandeln Sie Authentifizierungs- und Liefergarantien als separate Designprobleme. Überprüfung Localhost Tunnel Sicherheit und Webhook Zuverlässigkeitsmuster Bevor Sie sensible Daten verbinden.
