Para testar um Supabase Database Webhook em máquina local, use host.docker.internal quando Supabase e seu receptor funcionam em sua máquina, ou usar um túnel público HTTPS quando um projeto Supabase hospedado deve chamar seu aplicativo local. A distinção é importante: Postgres local funciona em Docker, onde localhost significa o recipiente de banco de dados, enquanto hospedado Supabase precisa de uma URL acessível pela internet.
O que o Supabase Database Webhooks envia
Database Webhooks reage ao Postgres INSERT, UPDATE, e DELETE operações numa tabela seleccionada. Supabase descreve-os como um invólucro assíncrono em torno de gatilhos usando o pg_net extensão. A transação que muda a linha não espera que seu receptor termine sua lógica de negócio, o que reduz o acoplamento, mas também significa que o receptor deve ser observável e ter conhecimento de falhas.
A carga útil JSON identifica a operação, esquema e tabela e inclui dados de linha. Para inserções e atualizações, record contém a nova linha. Para atualizações e exclusões, old_record fornece a linha anterior, quando disponível. Crie manipuladores em torno do envelope documentado em vez de tratar cada solicitação como apenas um objeto de linha.
Pilha local versus projeto hospedado
Supabase local para uma aplicação local: use o servidor Docker
Quando corres supabase start, Postgres está dentro de um recipiente. Um URL webhook como http://localhost:3000/api/supabase-db-hook volta para o contentor e normalmente falha. Supabase oficial Documentação Database Webhooks diz ao alvo host.docker.internal:
http://host.docker.internal:3000/api/supabase-db-hook
Esta rota não requer um túnel público. Nos motores Linux onde o nome do host não está disponível, use o mapeamento de portas de host suportado pela sua configuração Docker ou o endereço LAN da sua máquina, como sugerem os documentos Supabase. Confirme a partir de um recipiente, não apenas do navegador host.
Supabase hospedado para um aplicativo local: use HTTPS
Um banco de dados em nuvem não pode resolver o hostname Docker do seu laptop ou o endereço privado loopback. Iniciar a aplicação local e executar npx portpreview 3000, então configure:
https://your-subdomain.portpreview.dev/api/supabase-db-hook
Use um projeto de desenvolvimento dedicado ou tabela de baixo risco. Um webhook na nuvem pode incluir dados reais da linha, então expor uma tabela de produção a uma URL de desenvolvimento temporário é geralmente uma estratégia de teste ruim.
Criar um receptor que valide um segredo partilhado
Ao contrário de fornecedores que definem um cabeçalho HMAC obrigatório, um Database Webhook é uma solicitação de saída configurável HTTP. Proteja o endpoint com um cabeçalho secreto que você controla e configure o mesmo cabeçalho no webhook. TLS o protege em trânsito; uma comparação constante de tempo evita vazamentos de tempo secreto-prefixo através de sua aplicação.
// 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 });
}
Um cabeçalho compartilhado prova o conhecimento do segredo, mas não criptograficamente vincula esse segredo ao corpo. Se for necessária evidência de adulteração de nível corporal, envie o Database Webhook para um pequeno Edge Function confiável que valide seu próprio segredo de entrada, computa seu HMAC escolhido sobre um corpo de saída canônica, e o encaminha para o consumidor local ou de produção. Não inventes uma X-Supabase-Signature Assumir a menos que sua própria camada de encaminhamento cria e verifica-lo.
Configurar e ativar um webhook focado
- Escolha uma tabela de desenvolvimento e decida que operações importam.
- Crie o Database Webhook no Painel Supabase em Banco de Dados → Webhooks, selecionando o esquema, tabela e operações.
- Defina o URL local Docker ou o URL do túnel público descrito acima.
- Adicionar
Content-Type: application/jsone um aleatórioX-Webhook-Secretvalor onde a configuração do cabeçalho webhook está disponível. - Inicie o receptor e insira uma linha de teste claramente rotulada.
- Atualizar um campo, então excluir a linha, verificando todos os envelopes selecionados.
- Remover ou desativar o webhook de teste antes de alternar projetos ou fechar o túnel.
Nome linhas de teste assim limpeza é determinística. Não dispare uma integração em toda a mesa em registros de clientes de produção apenas para ver um pedido chegar.
Interpretar INSERT, UPDATE e DELETE com segurança
INSERT
Utilização record como o estado recentemente inserido. Se o receptor criar um objeto correspondente em outro lugar, armazene a chave primária da tabela fonte como uma chave de indempotência. Um evento de inserção pode ser entregue novamente durante o replay manual ou processamento de repetição personalizado.
UPDATE
Comparar record com old_record e agir apenas em domínios relevantes para a integração. Um webhook de atualização geral pode disparar para timestamps ou metadados não relacionados. Filtrar mudanças de negócios no-op evita chamadas a jusante caras.
DELETE
A linha apagada é representada por dados anteriores e não por um registro atual. Torne os manipuladores de exclusão tolerantes a campos opcionais ausentes e decida se a ação a jusante é exclusão, arquivo ou revogação. Preservar os requisitos de auditoria.
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;
}
A confiabilidade da entrega é uma preocupação da aplicação
Como Database Webhooks são solicitações de rede assíncrona, não trate o recebimento como uma transação distribuída com a mudança de linha de origem. Seu lado remoto pode não estar disponível após os commits Postgres. Monitore os resultados da solicitação de saída e design de reconciliação para qualquer coisa que não possa ser perdida.
Para fluxos de trabalho de alto valor, uma tabela da caixa de saída é mais forte: escreva uma mudança de negócio e uma linha da caixa de saída em uma transação de banco de dados, em seguida, deixe um trabalhador entregar com contadores de repetição explícitos, backoff, e manipulação de letras mortas. Um Database Webhook pode notificar o trabalhador, mas a reconciliação periódica ainda deve encontrar linhas de saída não entregues.
Faça o receptor idempotente. Uma chave útil combina esquema, tabela, operação, chave primária e uma versão estável da linha, como updated_at; para garantias estritas, adicione um evento imutável UUID em uma linha de saída. Evite hashing apenas a linha atual porque duas transições válidas podem produzir projeções semelhantes.
Chamando um Supabase Edge Function local
Se o destino for um Edge Function servido pela pilha local Supabase, o exemplo documentado é:
http://host.docker.internal:54321/functions/v1/my-function-name
O funcionário Guia de desenvolvimento Edge Functions utilizações supabase functions serve [function-name] para recarga local quente. Edge Functions requer verificação JWT por padrão. Para uma função webhook que não pode fornecer um usuário JWT, configure essa função deliberadamente, por exemplo com verify_jwt = false em supabase/config.toml, conforme documentado em Configuração da Função. Substituir a autenticação JWT com o seu cabeçalho secreto ou verificação de assinatura; desativar JWT sozinho torna a função pública.
Solução de problemas Supabase webhook localhost entrega
Ligação recusada da pilha local
Substituir localhost com host.docker.internal, verifique se o aplicativo se liga a uma interface acessível a partir de Docker, e confirme a porta. No Linux, configure a resolução do host-gateway ou use o IP do host. Um serviço ligado apenas a uma interface inesperada pode ainda rejeitar o tráfego de contentores.
O projeto hospedado nunca atinge a rota
Um projeto hospedado precisa da URL pública do túnel HTTPS, não do hostname Docker. Confirme que o túnel está ao vivo e sua URL inclui a rota completa. Verifique DNS/TLS postando-o você mesmo.
A rota devolve 401
Compare o nome e o valor do cabeçalho configurados, observe o espaço em branco principal ou posterior e reinicie o aplicativo após alterar as variáveis de ambiente. Registre se o cabeçalho existe, nunca seu valor. Se um intermediário tira cabeçalhos personalizados, use um convencional Authorization: Bearer ... cabeçalho e validá-lo explicitamente.
A forma da carga parece errada.
Registre apenas as chaves de nível superior, operação, esquema e tabela em desenvolvimento. Lembre-se que DELETE usa dados de linha anteriores e UPDATE pode incluir ambas as versões. Validar contra os exemplos de carga útil oficiais atuais antes de alterar seu analisador.
A atualização da base de dados é bem- sucedida, mas falta trabalho a jusante
Esse comportamento é possível em um projeto assíncrono. Inspecionar os registos de pedidos do Webhook e pg_net diagnósticos disponíveis em seu ambiente, em seguida, adicione retry ou reconciliação em vez de voltar uma transação de negócios já comprometida.
Verificação de segurança
- Use HTTPS para testes hospedados para locais e rode o segredo compartilhado temporário depois.
- Envie apenas colunas necessárias; evite expor tabelas sensíveis ou cargas de produção amplas.
- Validar um cabeçalho secreto antes de analisar ou persistir no corpo.
- Aplique roteamento POST-somente, limites de tamanho de solicitação, controles de taxa e logs editados.
- Use configurações de webhook locais, de encenação e de produção separadas.
- Crie repetições explícitas, idempotência, monitoramento e reconciliação para eventos importantes.
- Desabilitar URLs temporários do webhook de nuvem quando o túnel fechar.
O erro local mais comum é endereçamento de rede, não Postgres: uso de chamadas de conteúdo local host.docker.internal; chamadas de nuvem usam um túnel público. Uma vez que o tráfego chega, trate as garantias de autenticação e entrega como problemas de design separados. Revisão segurança do túnel localhost e padrões de confiabilidade webhook Antes de ligar dados sensíveis.
