Skip to content

Latest commit

Β 

History

History
128 lines (101 loc) Β· 4.81 KB

File metadata and controls

128 lines (101 loc) Β· 4.81 KB

Webhook Example

A sample project demonstrating the webhook pattern between a C# .NET 10 Minimal API with SignalR and a React + TypeScript frontend, fully containerized with Docker Compose.

Project structure

WebhookExample/
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ WebhookApi.csproj          (.NET 10)
β”‚   β”œβ”€β”€ Program.cs                  Minimal API + SignalR
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   β”œβ”€β”€ WebhookEvent.cs
β”‚   β”‚   └── WebhookListener.cs
β”‚   └── Hubs/
β”‚       └── WebhookHub.cs
└── frontend/
    β”œβ”€β”€ Dockerfile
    β”œβ”€β”€ nginx.conf
    β”œβ”€β”€ package.json
    β”œβ”€β”€ vite.config.ts
    └── src/
        β”œβ”€β”€ App.tsx                 Tabs + SignalR connection
        β”œβ”€β”€ index.css
        β”œβ”€β”€ types/webhook.ts
        β”œβ”€β”€ services/webhookService.ts
        └── components/
            β”œβ”€β”€ EventLog.tsx        Real-time event log
            β”œβ”€β”€ SendWebhook.tsx     Send webhook form
            └── Listeners.tsx       Listener CRUD

API endpoints (C# Minimal API)

Method Route Description
POST /api/webhooks/receive Receives a webhook, stores it and forwards it to all listeners
GET /api/webhooks/events Returns the last 100 events
DELETE /api/webhooks/events Clears all events
POST /api/webhooks/send Sends a webhook to any URL
POST /api/webhooks/listeners Registers a listener
GET /api/webhooks/listeners Lists all listeners
DELETE /api/webhooks/listeners/{id} Removes a listener
PATCH /api/webhooks/listeners/{id}/toggle Toggles a listener on/off
Hub /webhookHub SignalR hub for real-time updates

Run with Docker Compose

docker compose up --build

Local development (without Docker)

API:

cd api
dotnet run

Frontend:

cd frontend
npm install
npm run dev

The Vite dev server proxies requests to http://localhost:5000, so no additional CORS configuration is needed during development.


Example flow

  1. Open http://localhost:3000
  2. From the Send tab, fire a webhook to http://localhost:5000/api/webhooks/receive
  3. The event appears in real time in the Events tab via SignalR
  4. Register an external URL in the Listeners tab (e.g. https://webhook.site) β€” every incoming webhook will be automatically forwarded to it

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Docker Compose (network: webhook-net)                      β”‚
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  frontend :3000  β”‚        β”‚       api :5000           β”‚  β”‚
β”‚  β”‚  (nginx)         β”‚        β”‚   (.NET 10 Minimal API)   β”‚  β”‚
β”‚  β”‚                  β”‚        β”‚                           β”‚  β”‚
β”‚  β”‚  React + TS      │──HTTP──▢  POST /receive            β”‚  β”‚
β”‚  β”‚  (Vite build)    β”‚        β”‚  GET  /events             β”‚  β”‚
β”‚  β”‚                  │◀─WS────│  SignalR /webhookHub      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚                           β”‚  β”‚
β”‚         β–²                    β”‚  Forwards to listeners ──▢│  β”‚
β”‚         β”‚ proxy              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚    localhost:3000                                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key components

  • SignalR β€” The API pushes real-time notifications to the frontend whenever a webhook is received (WebhookReceived) or events are cleared (EventsCleared).
  • Listeners β€” Registered URLs that automatically receive an HTTP POST copy of every incoming webhook.
  • In-memory storage β€” Events and listeners are stored in memory (ConcurrentQueue / ConcurrentDictionary). Data is lost when the container restarts.

Environment variables (API)

Variable Default Description
ASPNETCORE_URLS http://+:5000 Listening port
ASPNETCORE_ENVIRONMENT Development Runtime environment