-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtest_webhook_example.py
More file actions
92 lines (77 loc) · 2.91 KB
/
Copy pathtest_webhook_example.py
File metadata and controls
92 lines (77 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import json
from email.message import Message
from io import BytesIO
from typing import Any
import pytest
from examples import webhook_server
from examples.webhook_server import (
WebhookHandler,
max_request_body_bytes,
processed_event_ids,
)
def _request(
content_length: str | None,
body: bytes = b"",
event_id: str | None = None,
) -> tuple[list[tuple[int, dict[str, Any]]], WebhookHandler]:
handler = WebhookHandler.__new__(WebhookHandler)
handler.path = "/calle/webhook"
handler.headers = Message()
if content_length is not None:
handler.headers["content-length"] = content_length
if event_id is not None:
handler.headers["CALL-E-Event-Id"] = event_id
handler.rfile = BytesIO(body)
handler.close_connection = False
responses: list[tuple[int, dict[str, Any]]] = []
handler._send_json = lambda status, payload: responses.append((status, payload))
handler.do_POST()
return responses, handler
@pytest.mark.parametrize(
("content_length", "expected_response"),
[
(None, (400, {"error": "invalid_content_length"})),
("invalid", (400, {"error": "invalid_content_length"})),
("-1", (400, {"error": "invalid_content_length"})),
(str(max_request_body_bytes + 1), (413, {"error": "payload_too_large"})),
],
)
def test_webhook_rejects_unsafe_content_lengths_before_reading(
content_length: str | None,
expected_response: tuple[int, dict[str, str]],
) -> None:
responses, handler = _request(content_length)
assert responses == [expected_response]
assert handler.rfile.tell() == 0
assert handler.close_connection is True
def test_webhook_accepts_valid_body_within_limit() -> None:
event_id = "evt_body_limit_control"
body = json.dumps(
{
"id": event_id,
"type": "call.completed",
"data": {"id": "call_123"},
}
).encode()
processed_event_ids.clear()
responses, _ = _request(str(len(body)), body, event_id)
assert responses == [(200, {"received": True})]
processed_event_ids.clear()
def test_webhook_bounds_local_deduplication_state(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(webhook_server, "max_processed_event_ids", 1)
processed_event_ids.clear()
for event_id in ("evt_first", "evt_second"):
body = json.dumps(
{"id": event_id, "type": "call.completed", "data": {"id": "call_123"}}
).encode()
responses, _ = _request(str(len(body)), body, event_id)
assert responses == [(200, {"received": True})]
assert len(processed_event_ids) == 1
duplicate_body = json.dumps(
{"id": "evt_second", "type": "call.completed", "data": {"id": "call_123"}}
).encode()
responses, _ = _request(str(len(duplicate_body)), duplicate_body, "evt_second")
assert responses == [(200, {"received": True, "duplicate": True})]
processed_event_ids.clear()