Skip to content

Commit 23e95de

Browse files
committed
docs: add Flask receiver example
1 parent 7fca54e commit 23e95de

File tree

18 files changed

+354
-150
lines changed

18 files changed

+354
-150
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export DJANGO_SETTINGS_MODULE=tests.settings
1+
export DJANGO_SETTINGS_MODULE=tests.settings.test

Dockerfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# syntax=docker/dockerfile:1.3-labs
2+
FROM python:3.12-bookworm
3+
4+
WORKDIR /app/
5+
6+
RUN pip install --upgrade pip poetry
7+
8+
COPY pyproject.toml poetry.lock /app/
9+
10+
RUN poetry config virtualenvs.create false && poetry install --no-interaction
11+
12+
COPY django_webhook /app/django_webhook
13+
COPY tests /app/tests
14+
COPY manage.py /app/manage.py
15+
16+
CMD /app/manage.py runserver_plus 0.0.0.0:8000

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ django-webhook-request-timestamp: 1697818014
4444
- Admin integration
4545
- Audit log with past webhook events
4646
- Protection from replay attacks
47+
- Allows rotating webhook secrets
4748

4849
### 📖 Documentation
4950

docker-compose.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
services:
2+
webhook_server: &defaults
3+
build:
4+
context: .
5+
ports:
6+
- "8000:8000"
7+
environment:
8+
DJANGO_SETTINGS_MODULE: tests.settings
9+
volumes:
10+
- ./tests:/app/tests
11+
- ./django_webhook:/app/django_webhook
12+
13+
webhook_worker:
14+
<<: *defaults
15+
ports: []
16+
command: celery --app tests.celery_app:app worker --loglevel=INFO
17+
18+
postgres:
19+
image: postgres:14
20+
container_name: postgres
21+
environment:
22+
POSTGRES_DB: postgres
23+
POSTGRES_USER: postgres
24+
POSTGRES_PASSWORD: postgres
25+
volumes:
26+
- pgdata:/var/lib/postgresql/data
27+
ports: ['5432:5432']
28+
29+
redis:
30+
image: redis
31+
ports:
32+
- "6379:6379"
33+
34+
nodejs_receiver:
35+
build:
36+
context: examples/nodejs
37+
ports:
38+
- "8001:8001"
39+
40+
flask_receiver:
41+
build:
42+
context: examples/flask
43+
ports:
44+
- "8002:8002"
45+
volumes:
46+
- ./examples/flask:/app/
47+
48+
volumes:
49+
pgdata:

examples/flask/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# syntax=docker/dockerfile:1.3-labs
2+
FROM python:3.12-bookworm
3+
4+
WORKDIR /app/
5+
6+
RUN pip install --upgrade pip flask
7+
8+
COPY server.py /app/server.py
9+
10+
CMD flask --app server.py --debug run --host 0.0.0.0 --port 8002

examples/flask/server.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import hmac
2+
from hashlib import sha256
3+
4+
from flask import Flask, Response, request
5+
6+
app = Flask(__name__)
7+
8+
webhook_secret = "very-secret-token"
9+
10+
11+
@app.route("/webhook", methods=["POST"])
12+
def webhook():
13+
signatures_str = request.headers.get("Django-Webhook-Signature-v1", "")
14+
signatures = signatures_str.split(",")
15+
timestamp = request.headers["Django-Webhook-Request-Timestamp"]
16+
17+
for signature in signatures:
18+
digest_payload = bytes(timestamp, "utf8") + b":" + request.data
19+
digest = hmac.new(
20+
key=webhook_secret.encode(),
21+
msg=digest_payload,
22+
digestmod=sha256,
23+
)
24+
signature_valid = hmac.compare_digest(digest.hexdigest(), signature)
25+
if not signature_valid:
26+
app.logger.warning("Invalid signature from incoming webhook")
27+
return Response("Invalid signature", status=400)
28+
29+
app.logger.info(request.json)
30+
return Response("Webhook received.", status=200)

manage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66

77
if __name__ == "__main__":
8-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings")
8+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings.local")
99
from django.core.management import execute_from_command_line
1010

1111
execute_from_command_line(sys.argv)

mypy.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ignore_missing_imports = True
44
plugins = mypy_django_plugin.main
55

66
[mypy.plugins.django-stubs]
7-
django_settings_module = tests.settings
7+
django_settings_module = tests.settings.test
88

99
[mypy-webhooks.migrations.*]
1010
ignore_errors = True

0 commit comments

Comments
 (0)