Все статьи
События вставки, обновления и удаления строк Postgres, передаваемые из базы Supabase в защищённую локальную конечную точку вебхука.
Supabasedatabase webhooksPostgreslocal development

Как тестировать Supabase Database Webhooks на localhost

Для тестирования Supabase Database Webhook на локальном хосте используйте host.docker.internal когда и Supabase, и ваш приемник работают на вашем компьютере или используют публичный туннель HTTPS, когда размещенный проект Supabase должен позвонить в ваше локальное приложение. Postgres работает в Docker, где localhost Контейнер базы данных, в то время как размещенный Supabase нуждается в доступном в Интернете URL.

Что посылает Supabase Database Webhooks

Database Webhooks реагирует на Postgres INSERT, UPDATEи DELETE Операции на выбранном столе. Supabase описывает их как асинхронную обертку вокруг триггеров. pg_net расширение. Транзакция, которая меняет строку, не ждет, пока ваш получатель закончит свою бизнес-логику, что снижает связь, но также означает, что приемник должен быть наблюдаемым и осведомлен о сбоях.

Полезная нагрузка JSON идентифицирует операцию, схему и таблицу и включает в себя данные строк. для вставок и обновлений, record Содержит новый ряд. для обновления и удаления, old_record Предыдущие строки там, где они доступны. Постройте обработчиков вокруг задокументированного конверта, а не рассматривайте каждый запрос как объект строки.

Локальный стек против размещенного проекта

Локальный Supabase для локального приложения: используйте хост Docker

Когда бегаешь supabase startPostgres находится внутри контейнера. Webhook URL, например http://localhost:3000/api/supabase-db-hook Он возвращается в контейнер и обычно выходит из строя. Официальный сайт Supabase Документация Database Webhooks Говорит цель host.docker.internal:

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

Для этого маршрута не нужен общественный тоннель. В двигателях Linux, где это имя хоста недоступно, используйте отображение шлюза хоста, поддерживаемое вашей установкой Docker или адресом локальной сети вашей машины, как предлагают документы Supabase. Подтверждается из контейнера, а не только из браузера хоста.

Хостинг Supabase в локальном приложении: используйте HTTPS

Облачная база данных не может решить имя хоста вашего ноутбука Docker или частный адрес обратной связи. Запустите локальное приложение и запустите npx portpreview 3000затем настроить:

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

Используйте специальный проект разработки или таблицу низкого риска. Облачный веб-хук может включать в себя реальные данные строк, поэтому представление производственной таблицы временному URL-адресу разработки обычно является плохой стратегией тестирования.

Создайте приемник, который подтверждает общий секрет

В отличие от провайдеров, которые определяют обязательный заголовок HMAC, Database Webhook является настраиваемым исходящим запросом HTTP. Защитите конечную точку с помощью секретного заголовка, который вы контролируете, и настройте тот же заголовок на веб-книге. TLS защищает его при транспортировке; сравнение в постоянное время позволяет избежать утечки тайного времени префикса через ваше приложение.

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

Общий заголовок доказывает знание секрета, но не криптографически связывает этот секрет с телом. Если требуется доказательство подделки на уровне тела, отправьте Database Webhook в небольшой доверенный Edge Function, который проверяет свой собственный входящий секрет, вычисляет выбранный вами HMAC по каноническому исходящему телу и пересылает его местному или производственному потребителю. Не изобретайте ни одного X-Supabase-Signature Допущение, если только ваш собственный слой пересылки не создает и не проверяет его.

Настройка и запуск сфокусированного webhook

  1. Выберите таблицу разработки и решите, какие операции имеют значение.
  2. Создайте Database Webhook в панели управления Supabase в разделе База данных → Webhooks, выбрав схему, таблицу и операции.
  3. Установите локальный URL Docker или общедоступный URL-адрес туннеля, описанный выше.
  4. Добавить Content-Type: application/json и случайный X-Webhook-Secret значение, при котором доступна конфигурация заголовка webhook.
  5. Запустите приемник и вставьте четко обозначенный тестовый ряд.
  6. Обновите одно поле, затем удалите строку, проверив все выбранные конверты.
  7. Удалите или отключите тестовый веб-хук перед переключением проектов или закрытием туннеля.

Тестовые ряды имен, поэтому очистка детерминирована. Не запускайте всестороннюю интеграцию в производственных записях клиентов только для того, чтобы получить запрос.

Интерпретация INSERT, UPDATE и DELETE безопасно

INSERT

Использовать record как вновь введенное государство. Если приемник создает соответствующий объект в другом месте, храните первичный ключ исходной таблицы в качестве ключа идемпотентности. Событие вставки может быть доставлено снова во время ручного воспроизведения или обработки на заказ.

UPDATE

сравнивать record с old_record и действовать только в областях, имеющих отношение к интеграции. Общий веб-хук обновления может работать для временных меток или несвязанных метаданных. Фильтрация безоперационных изменений бизнеса предотвращает дорогостоящие звонки вниз по течению.

DELETE

Удаленная строка представлена предыдущими данными, а не текущей записью. Сделайте обработчиков удаления терпимыми к отсутствующим дополнительным полям и решите, является ли действие вниз по течению удалением, архивным или аннулированием. Сохранить требования аудита.

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

Надежность доставки является проблемой приложения

Поскольку Database Webhooks является асинхронным сетевым запросом, не рассматривайте квитанцию как распределенную транзакцию с изменением исходной строки. Ваша удаленная сторона может быть недоступна после совершения Postgres. Мониторинг исходящих результатов запроса и согласование дизайна для всего, что не может быть потеряно.

Для высокоценных рабочих процессов таблица отправки сильнее: напишите изменение бизнеса и строку отправки в одной транзакции базы данных, а затем позвольте работнику доставить с явными счетчиками повторных попыток, обратной связью и обработкой мертвой буквы. Database Webhook может уведомить работника, но периодическая сверка все равно должна найти непоставленные ряды аутбоксов.

Сделайте приемник идемпотентным. Полезный ключ сочетает в себе схему источника, таблицу, операцию, первичный ключ и стабильную версию строки, такую как updated_at; для строгих гарантий добавьте неизменное событие UUID в строку аутбокса. Избегайте хеширования только текущего ряда, потому что два действительных перехода могут производить аналогичные проекции.

Supabase Edge Function

Если местом назначения является Edge Function, обслуживаемый локальным стеком Supabase, документированным примером является:

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

Официальный Руководство по развитию Edge Functions использование supabase functions serve [function-name] для локальной горячей перезагрузки. Edge Functions требует проверки JWT по умолчанию. Для функции webhook, которая не может поставлять пользователю JWT, настройте эту функцию преднамеренно, например, verify_jwt = false в supabase/config.tomlКак документировано в Конфигурация функцийЗамените аутентификацию JWT на проверку секретного заголовка или подписи; отключение JWT само по себе делает функцию общедоступной.

Устранение неполадок Supabase webhook localhost delivery

Подключение отказали из местного стека

Заменить localhost с host.docker.internalПроверьте, связывается ли приложение с интерфейсом, доступным из Docker, и подтвердите порт. На Linux настройте разрешение шлюза хоста или используйте IP-адрес хоста. Служба, связанная только с неожиданным интерфейсом, может отклонить контейнерный трафик.

Проект никогда не достигает маршрута

Размещенный проект нуждается в общедоступном URL-адресе туннеля HTTPS, а не в имени хоста Docker. Подтвердите, что туннель находится в режиме реального времени, и его URL-адрес включает полный маршрут. Проверьте DNS/TLS, опубликовав его самостоятельно.

Маршрут возвращается 401

Сравните настроенное имя и значение заголовка, посмотрите на ведущее или заднее белое пространство и перезапустите приложение после изменения переменных среды. Регистрируйте, существует ли заголовок, никогда его значение. Если посредник полоскает пользовательские заголовки, используйте обычные Authorization: Bearer ... Заголовок и проверить его явно.

Форма груза кажется неправильной

Логируйте только ключи верхнего уровня, операцию, схему и таблицу в разработке. Помните, что DELETE использует данные предыдущих строк, и UPDATE может включать обе версии. Проверяйте текущие официальные примеры полезной нагрузки, прежде чем менять парсер.

Обновление базы данных успешно, но работа по нисходящему потоку отсутствует

Такое поведение возможно в асинхронном дизайне. Проверьте журналы запросов webhook и pg_net Диагностика, доступная в вашей среде, затем добавьте повторную попытку или сверку, а не откатывайте уже совершенную деловую транзакцию.

Контрольный список безопасности

  • Используйте HTTPS для проведения локальных тестов и затем поверните временный общий секрет.
  • Отправляйте только необходимые колонки; избегайте разоблачения чувствительных таблиц или широких полезных нагрузок.
  • Проверяйте секретный заголовок перед разбором или сохранением тела.
  • Примените маршрутизацию POST, ограничения размера запроса, контроль скорости и отредактированные журналы.
  • Используйте отдельные локальные, постановочные и производственные конфигурации webhook.
  • Создавайте явные повторы, идемпотентность, мониторинг и примирение для важных событий.
  • Отключите временные облачные URL-адреса, когда туннель закрывается.

Наиболее распространенной локальной ошибкой является сетевая адресация, а не Postgres: использование вызовов локального контейнера. host.docker.internalОблачные звонки используют общественный туннель. Как только трафик поступает, рассматривайте аутентификацию и гарантии доставки как отдельные проблемы проектирования. Обзор локальный туннель безопасности и шаблоны надежности web-cook перед подключением конфиденциальных данных.

Часто задаваемые вопросы

Почему Supabase Database Webhook не достигает локального хоста?
Локальный Supabase Postgres работает в Docker, поэтому локальный хост относится к контейнеру. Используйте host.docker.internal или ваш хост IP. Вместо этого для проекта Supabase нужен публичный URL-адрес туннеля HTTPS.
Нужен ли мне туннель для местного Supabase Database Webhooks?
Не тогда, когда Supabase и приемник являются локальными; используйте маршрутизацию хоста Docker. Вам нужен туннель, когда размещенный проект Supabase должен вызвать приложение, работающее на вашем компьютере.
Подписаны ли автоматически Supabase Database Webhooks?
Не используйте заголовок HMAC. Настройка и проверка общего секретного заголовка. Если вам нужна подпись, связанная с телом, перейдите через доверенную функцию, которая создает HMAC.
Какие данные отправляет Supabase Database Webhook?
Оболочка JSON идентифицирует INSERT, UPDATE или DELETE плюс схему и таблицу. Он включает в себя новую запись для вставок и обновлений и предыдущие данные строк для обновлений или удалений, где это возможно.