diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index b63d6486f1..504388c05a 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -265,6 +265,12 @@ def files(self): def size_of_file(self, file): return file.size + def parsed_body(self): + try: + return self.request.data + except AttributeError: + return RequestExtractor.parsed_body(self) + def _set_user_info(request, event): # type: (WSGIRequest, Dict[str, Any]) -> None diff --git a/tests/integrations/django/myapp/urls.py b/tests/integrations/django/myapp/urls.py index 20c01e9dd6..fea7cb31d1 100644 --- a/tests/integrations/django/myapp/urls.py +++ b/tests/integrations/django/myapp/urls.py @@ -32,5 +32,13 @@ path("template-exc", views.template_exc, name="template_exc"), ] + +try: + urlpatterns.append( + path("rest-framework-exc", views.rest_framework_exc, name="rest_framework_exc") + ) +except AttributeError: + pass + handler500 = views.handler500 handler404 = views.handler404 diff --git a/tests/integrations/django/myapp/views.py b/tests/integrations/django/myapp/views.py index edac7800e2..0b75ef54ea 100644 --- a/tests/integrations/django/myapp/views.py +++ b/tests/integrations/django/myapp/views.py @@ -4,6 +4,18 @@ from django.shortcuts import render from django.views.generic import ListView +try: + from rest_framework.decorators import api_view + + @api_view(["POST"]) + def rest_framework_exc(request): + 1 / 0 + + +except ImportError: + pass + + import sentry_sdk diff --git a/tests/integrations/django/test_basic.py b/tests/integrations/django/test_basic.py index 871f324632..3e135fb52b 100644 --- a/tests/integrations/django/test_basic.py +++ b/tests/integrations/django/test_basic.py @@ -1,4 +1,5 @@ import pytest +import json from werkzeug.test import Client from django.contrib.auth.models import User @@ -389,3 +390,68 @@ def test_template_exception(sentry_init, client, capture_events): (None, None), (u"invalid_block_tag", u"django.template.base"), ] + + +@pytest.mark.parametrize( + "type,event_request", + [ + [ + "json", + { + "cookies": {}, + "data": {"foo": "bar"}, + "env": {"SERVER_NAME": "localhost", "SERVER_PORT": "80"}, + "headers": { + "Content-Length": "14", + "Content-Type": "application/json", + "Host": "localhost", + }, + "method": "POST", + "query_string": "", + "url": "http://localhost/rest-framework-exc", + }, + ], + [ + "formdata", + { + "cookies": {}, + "data": {"foo": "bar"}, + "env": {"SERVER_NAME": "localhost", "SERVER_PORT": "80"}, + "headers": { + "Content-Length": "7", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "localhost", + }, + "method": "POST", + "query_string": "", + "url": "http://localhost/rest-framework-exc", + }, + ], + ], +) +def test_rest_framework_basic( + sentry_init, client, capture_events, capture_exceptions, type, event_request +): + pytest.importorskip("rest_framework") + sentry_init(integrations=[DjangoIntegration()], send_default_pii=True) + exceptions = capture_exceptions() + events = capture_events() + + if type == "json": + client.post( + reverse("rest_framework_exc"), + data=json.dumps({"foo": "bar"}), + content_type="application/json", + ) + elif type == "formdata": + client.post(reverse("rest_framework_exc"), data={"foo": "bar"}) + else: + assert False + + error, = exceptions + assert isinstance(error, ZeroDivisionError) + + event, = events + assert event["exception"]["values"][0]["mechanism"]["type"] == "django" + + assert event["request"] == event_request diff --git a/tox.ini b/tox.ini index e4d39485de..6c7089dd80 100644 --- a/tox.ini +++ b/tox.ini @@ -41,7 +41,7 @@ envlist = deps = -r test-requirements.txt - py{2.7,3.4,3.5,3.6,3.7}-django: psycopg2>=2.7.5 + django-{1.11,2.0,2.1}: djangorestframework>=3.0.0,<4.0.0 django-{1.6,1.7,1.8}: pytest-django<3.0 django-{1.9,1.10,1.11,2.0,2.1,dev}: pytest-django>=3.0