JAVASCRIPT
Node.js: Creating a Simple Webhook Listener with Express
Set up a robust Node.js Express server to listen for and process incoming webhook POST requests, ensuring secure handling of event payloads from external APIs.
const express = require('express');
const bodyParser = require('body-parser'); // For parsing JSON/URL-encoded bodies
const crypto = require('crypto'); // For verifying signatures if provided by webhook source
const app = express();
const port = 3000;
// Middleware to parse JSON bodies
app.use(bodyParser.json());
// Example secret key for webhook signature verification (replace with a strong, environment-variable key)
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'your-super-secret-key';
// Webhook listener endpoint
app.post('/webhook', (req, res) => {
console.log('Received webhook request.');
// --- Optional: Webhook Signature Verification ---
// Many webhook providers send a signature in a header (e.g., 'X-Hub-Signature', 'X-Stripe-Signature')
// This helps ensure the request truly came from the expected source and hasn't been tampered with.
// Example for GitHub-like HMAC-SHA256 signature verification:
const signature = req.headers['x-hub-signature-256']; // Or whatever header your provider uses
if (signature) {
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
const digest = 'sha256=' + hmac.update(JSON.stringify(req.body)).digest('hex'); // Use raw body for verification if available
// Note: Some webhook providers require verifying the *raw* request body before parsing.
// If you need the raw body for verification, use a custom bodyParser or put this check before app.use(bodyParser.json())
// and access req.rawBody (if a custom middleware adds it) or req.body before it's parsed.
// For simplicity, here we're using the already parsed body.
if (digest !== signature) {
console.warn('Webhook signature mismatch. Request might be invalid or tampered with.');
return res.status(401).send('Signature verification failed.');
}
console.log('Webhook signature verified successfully.');
} else {
console.log('No webhook signature provided (or not configured). Proceeding without verification.');
}
// --- End Signature Verification ---
const eventPayload = req.body;
console.log('Webhook Payload:', eventPayload);
// Process the webhook payload based on its type or content
if (eventPayload.event_type === 'user.created') {
console.log(`New user created: ${eventPayload.user.email}`);
// Perform actions like sending a welcome email, updating a CRM, etc.
} else if (eventPayload.event_type === 'payment.succeeded') {
console.log(`Payment successful for order: ${eventPayload.order_id}`);
// Update order status, fulfill subscription, etc.
} else {
console.log(`Unhandled event type: ${eventPayload.event_type}`);
}
// Respond to the webhook sender to acknowledge receipt
// A 200 OK status is generally expected within a few seconds.
res.status(200).send('Webhook received and processed.');
});
app.listen(port, () => {
console.log(`Webhook listener running on http://localhost:${port}`);
console.log('Waiting for incoming webhook requests...');
});
// To test locally, you can use a tool like ngrok to expose your local server
// ngrok http 3000
How it works: This Node.js Express snippet creates a server that listens for incoming HTTP POST requests, commonly used for webhooks. It uses `body-parser` to automatically parse JSON payloads. The core logic resides in the `/webhook` endpoint, which receives the payload and processes it based on the `event_type`. Crucially, it includes an optional but highly recommended section for webhook signature verification using Node.js's `crypto` module. This ensures that the incoming request genuinely originates from the expected source and has not been tampered with, enhancing the security of your API integrations. The server responds with a 200 OK status to acknowledge receipt.