Improve reusability of the webhook handler to allow converting the route to a Pages Router API Route. (#110)

This commit is contained in:
Giancarlo Buomprisco
2025-02-04 08:46:52 +07:00
committed by GitHub
parent 2a157e8baa
commit fcdae7aa65
4 changed files with 23 additions and 15 deletions

View File

@@ -10,8 +10,19 @@ export const POST = enhanceRouteHandler(
const service = getDatabaseWebhookHandlerService();
try {
const signature = request.headers.get('X-Supabase-Event-Signature');
if (!signature) {
return new Response('Missing signature', { status: 400 });
}
const body = await request.clone().json();
// handle the webhook event
await service.handleWebhook(request);
await service.handleWebhook({
body,
signature,
});
// return a successful response
return new Response(null, { status: 200 });

View File

@@ -28,13 +28,13 @@ class DatabaseWebhookHandlerService {
/**
* @name handleWebhook
* @description Handle the webhook event
* @param request
* @param params
*/
async handleWebhook(
request: Request,
params?: {
handleEvent<Table extends keyof Tables>(
params: {
body: RecordChange<keyof Tables>;
signature: string;
handleEvent?<Table extends keyof Tables>(
payload: Table extends keyof Tables
? DatabaseChangePayload<Table>
: never,
@@ -42,9 +42,7 @@ class DatabaseWebhookHandlerService {
},
) {
const logger = await getLogger();
const json = await request.clone().json();
const { table, type } = json as RecordChange<keyof Tables>;
const { table, type } = params.body;
const ctx = {
name: this.namespace,
@@ -57,7 +55,7 @@ class DatabaseWebhookHandlerService {
// check if the signature is valid
const verifier = await getDatabaseWebhookVerifier();
await verifier.verifySignatureOrThrow(request);
await verifier.verifySignatureOrThrow(params.signature);
// all good, we can now the webhook
@@ -68,11 +66,12 @@ class DatabaseWebhookHandlerService {
try {
// handle the webhook event based on the table
await service.handleWebhook(json);
await service.handleWebhook(params.body);
// if a custom handler is provided, call it
if (params?.handleEvent) {
await params.handleEvent(json);
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
await params.handleEvent(params.body as any);
}
logger.info(ctx, 'Webhook processed successfully');

View File

@@ -1,3 +1,3 @@
export abstract class DatabaseWebhookVerifierService {
abstract verifySignatureOrThrow(request: Request): Promise<boolean>;
abstract verifySignatureOrThrow(header: string): Promise<boolean>;
}

View File

@@ -17,9 +17,7 @@ export function createDatabaseWebhookVerifierService() {
class PostgresDatabaseWebhookVerifierService
implements DatabaseWebhookVerifierService
{
verifySignatureOrThrow(request: Request) {
const header = request.headers.get('X-Supabase-Event-Signature');
verifySignatureOrThrow(header: string) {
if (header !== webhooksSecret) {
throw new Error('Invalid signature');
}