Esempi di webhook
Questa pagina offre esempi completi e pronti per la produzione per ricevere ed elaborare i webhook Ignite in diversi linguaggi di programmazione.
Esempi di server completi
Next.js API Routes
// pages/api/webhook.ts
import { createHmac, timingSafeEqual } from "crypto";
import { NextApiRequest, NextApiResponse } from "next";
// Disable body parser to access raw body for signature verification
export const config = {
api: {
bodyParser: false,
},
};
interface ThumbnailFormat {
url: string;
fileSize: number;
}
interface ThumbnailVariant {
name: string;
width: number;
height: number;
formats: {
jpeg: ThumbnailFormat;
webp: ThumbnailFormat;
};
}
interface VideoWebhookData {
id: string;
status: "COMPLETE" | "PROCESSING" | "NO_FILE" | "FAILED";
title: string;
src?: {
thumbnails?: ThumbnailVariant[];
thumbnailUrl?: string; // deprecated — use src.thumbnails instead
mp4?: Array<{ name: string; url: string; width: number; height: number }>;
};
// ... other video properties
}
async function getRawBody(req: NextApiRequest): Promise<string> {
const chunks: Buffer[] = [];
for await (const chunk of req) {
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
}
return Buffer.concat(chunks).toString("utf-8");
}
function isValidSignature(
rawBody: string,
signatureHeader: string | string[] | undefined,
secret: string
): boolean {
try {
if (typeof signatureHeader !== "string") {
return false;
}
const time = signatureHeader.match(/t=(\d+)/)?.[1];
const token = signatureHeader.match(/v1=(\w+)/)?.[1];
if (!time || !token) {
return false;
}
const signedPayload = `${time}.${rawBody}`;
const hmac = createHmac("sha256", secret);
const calculatedSignature = hmac.update(signedPayload).digest("hex");
return timingSafeEqual(
Buffer.from(token),
Buffer.from(calculatedSignature)
);
} catch {
return false;
}
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
return res.status(405).end();
}
const rawBody = await getRawBody(req);
if (
!isValidSignature(
rawBody,
req.headers["x-webhook-signature"],
process.env.WEBHOOK_SIGNING_SECRET!
)
) {
console.error("Invalid webhook signature");
return res.status(403).end();
}
const eventType = req.headers["x-webhook-event"];
const deliveryId = req.headers["x-webhook-delivery-id"];
const video = JSON.parse(rawBody) as VideoWebhookData;
// Process based on event type
switch (eventType) {
case "video.created":
console.log("New video created:", video.id, video.title);
// await handleVideoCreated(video);
break;
case "video.updated":
console.log("Video updated:", video.id, video.title);
if (video.status === "COMPLETE") {
// Video processing finished - update your database
// await db.updateVideo(video.id, {
// thumbnails: video.src?.thumbnails,
// thumbnail: video.src?.thumbnails?.[0]?.formats.jpeg.url,
// sizes: video.src?.mp4,
// });
}
break;
case "video.deleted":
console.log("Video deleted:", video.id);
// await handleVideoDeleted(video);
break;
}
return res.status(204).end();
}Consegne webhook
Ogni tentativo di consegna webhook viene registrato. Se una consegna fallisce, il sistema riprova automaticamente.
Stato della consegna
| Stato | Descrizione |
|---|---|
success | Evento consegnato con successo (risposta HTTP 2xx) |
failed | Consegna fallita (timeout, HTTP 4xx/5xx, errore di rete) |
Informazioni sulla consegna
Ogni record di consegna contiene:
| Campo | Descrizione |
|---|---|
responseCode | Codice di stato HTTP restituito dal tuo endpoint |
responseBody | Corpo della risposta del tuo endpoint (troncato per risposte grandi) |
errorMessage | Messaggio di errore se la consegna è fallita |
deliveredAt | Timestamp del tentativo di consegna |
attemptNumber | Numero del tentativo (si incrementa con i retry) |
nextRetryAt | Quando verrà tentato il prossimo retry (se applicabile) |
Comportamento dei retry
- Le consegne fallite vengono riprovate automaticamente
- Se
nextRetryAtè impostato, è pianificato un retry - Se
nextRetryAtnon è impostato, non verranno effettuati altri retry
Buone pratiche
Seguire queste buone pratiche garantisce un’elaborazione affidabile dei webhook e aiuta a risolvere i problemi.
Tempo di risposta
Il tuo endpoint deve rispondere entro 30 secondi. Per operazioni lunghe, conferma subito la ricezione del webhook ed elabora in modo asincrono:
app.post('/webhook', async (req, res) => {
// Immediately acknowledge receipt
res.status(200).json({ received: true });
// Process asynchronously (don't await)
processWebhookAsync(req.body).catch(console.error);
});
async function processWebhookAsync(video) {
// Long-running operations here
}Sicurezza
- Proteggi i segreti — Non esporre mai il signing secret nel codice lato client o nel controllo versione
- Usa HTTPS — In produzione usa sempre endpoint HTTPS
- Valida tutto — Verifica sempre le firme prima di elaborare
- Rate limiting — Valuta di applicare il rate limiting sul tuo endpoint
Affidabilità
- Idempotenza — Memorizza e controlla
X-Webhook-Delivery-Idper gestire consegne duplicate - Logging — Registra tutte le richieste webhook per il debug
- Monitoraggio — Imposta avvisi per elaborazioni webhook fallite
- Gestione errori — Restituisci codici di stato HTTP appropriati così i retry funzionano correttamente
Codici di stato HTTP
| Codice | Significato |
|---|---|
200-299 | Successo — evento elaborato |
4xx | Errore client — verrà riprovato |
5xx | Errore server — verrà riprovato |
Risoluzione dei problemi
Nessun evento ricevuto
- Controlla che la sottoscrizione webhook sia impostata su Active
- Verifica che siano selezionati i tipi di evento corretti
- Assicurati che gli eventi avvengano nel workspace corretto
- Controlla i log del server per le richieste in arrivo
La verifica della firma fallisce
- Verifica di usare il signing secret corretto (non un token API)
- Assicurati che il corpo della richiesta non venga modificato prima della verifica
- Controlla che la serializzazione JSON coincida (compatta, senza spazi extra)
- Verifica che il formato dell’intestazione firma sia analizzato correttamente:
t=timestamp,v1=signature
Errori di timeout
- Rispondi entro 30 secondi
- Sposta le operazioni lunghe in elaborazione in background
- Restituisci subito
200, elabora in modo asincrono
Eventi duplicati
- Implementa l’idempotenza usando
X-Webhook-Delivery-Id - Controlla
attemptNumberper i retry - Memorizza gli ID di consegna elaborati in un database