Skip to content

Commit afe0232

Browse files
authored
feat: Tornado formdata (#296)
* feat: Tornado formdata * fix: Toxpath * fix: Linters
1 parent f5503df commit afe0232

File tree

4 files changed

+73
-9
lines changed

4 files changed

+73
-9
lines changed

scripts/runtox.sh

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
#!/bin/bash
22
set -e
33

4-
if [ -z "$TOXPATH" ]; then
4+
if [ -n "$TOXPATH" ]; then
5+
true
6+
elif which tox &> /dev/null; then
57
TOXPATH=tox
8+
else
9+
TOXPATH=./.venv/bin/tox
610
fi
711

812
# Usage: sh scripts/runtox.sh py3.7 <pytest-args>

sentry_sdk/integrations/tornado.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ def raw_data(self):
173173

174174
def form(self):
175175
# type: () -> Optional[Any]
176-
# TODO: Where to get formdata and nothing else?
177-
return None
176+
return {
177+
k: [v.decode("latin1", "replace") for v in vs]
178+
for k, vs in self.request.body_arguments.items()
179+
}
178180

179181
def is_json(self):
180182
# type: () -> bool

tests/conftest.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616

1717
@pytest.fixture(autouse=True)
1818
def reraise_internal_exceptions(request, monkeypatch):
19+
errors = []
1920
if "tests_internal_exceptions" in request.keywords:
2021
return
2122

22-
def _capture_internal_exception(exc_info):
23-
reraise(*exc_info)
23+
def _capture_internal_exception(self, exc_info):
24+
errors.append(exc_info)
25+
26+
@request.addfinalizer
27+
def _():
28+
for e in errors:
29+
reraise(*e)
2430

2531
monkeypatch.setattr(
26-
sentry_sdk.Hub.current,
27-
"_capture_internal_exception",
28-
_capture_internal_exception,
32+
sentry_sdk.Hub, "_capture_internal_exception", _capture_internal_exception
2933
)
3034

3135

tests/integrations/tornado/test_tornado.py

+55-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import json
2+
13
import pytest
24

35
from sentry_sdk import configure_scope
4-
56
from sentry_sdk.integrations.tornado import TornadoIntegration
67

78
from tornado.web import RequestHandler, Application, HTTPError
@@ -136,3 +137,56 @@ def get(self):
136137
assert exception["type"] == "ZeroDivisionError"
137138

138139
assert "user" not in event
140+
141+
142+
def test_formdata(tornado_testcase, sentry_init, capture_events):
143+
sentry_init(integrations=[TornadoIntegration()], send_default_pii=True)
144+
events = capture_events()
145+
146+
class FormdataHandler(RequestHandler):
147+
def post(self):
148+
raise ValueError(json.dumps(sorted(self.request.body_arguments)))
149+
150+
client = tornado_testcase(Application([(r"/form", FormdataHandler)]))
151+
152+
response = client.fetch(
153+
"/form?queryarg=1",
154+
method="POST",
155+
headers={"Content-Type": "application/x-www-form-urlencoded"},
156+
body=b"field1=value1&field2=value2",
157+
)
158+
159+
assert response.code == 500
160+
161+
event, = events
162+
exception, = event["exception"]["values"]
163+
assert exception["value"] == '["field1", "field2"]'
164+
assert event["request"]["data"] == {"field1": ["value1"], "field2": ["value2"]}
165+
166+
167+
def test_json(tornado_testcase, sentry_init, capture_events):
168+
sentry_init(integrations=[TornadoIntegration()], send_default_pii=True)
169+
events = capture_events()
170+
171+
class FormdataHandler(RequestHandler):
172+
def post(self):
173+
raise ValueError(json.dumps(sorted(self.request.body_arguments)))
174+
175+
client = tornado_testcase(Application([(r"/form", FormdataHandler)]))
176+
177+
response = client.fetch(
178+
"/form?queryarg=1",
179+
method="POST",
180+
headers={"Content-Type": "application/json"},
181+
body=b"""
182+
{"foo": {"bar": 42}}
183+
""",
184+
)
185+
186+
assert response.code == 500
187+
188+
event, = events
189+
exception, = event["exception"]["values"]
190+
assert exception["value"] == "[]"
191+
assert event
192+
assert event["request"]["data"] == {"foo": {"bar": 42}}

0 commit comments

Comments
 (0)