Skip to content

Commit afa00ed

Browse files
authored
don't touch body if capture_body is False (#817)
So far, we still looked at the request body, even if capture_body was disabled. This was so we only set the `[REDACTED]` flag if there actually was a body. Unfortunately, this interferes with streaming requests. Fixes #816
1 parent e27e8a4 commit afa00ed

File tree

4 files changed

+56
-43
lines changed

4 files changed

+56
-43
lines changed

elasticapm/contrib/django/client.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -131,21 +131,25 @@ def get_data_from_request(self, request, event_type):
131131
result["headers"] = request_headers
132132

133133
if request.method in constants.HTTP_WITH_BODY:
134-
content_type = request.META.get("CONTENT_TYPE")
135-
if content_type == "application/x-www-form-urlencoded":
136-
data = compat.multidict_to_dict(request.POST)
137-
elif content_type and content_type.startswith("multipart/form-data"):
138-
data = compat.multidict_to_dict(request.POST)
139-
if request.FILES:
140-
data["_files"] = {field: file.name for field, file in compat.iteritems(request.FILES)}
141-
else:
142-
try:
143-
data = request.body
144-
except Exception as e:
145-
self.logger.debug("Can't capture request body: %s", compat.text_type(e))
146-
data = "<unavailable>"
147134
capture_body = self.config.capture_body in ("all", event_type)
148-
result["body"] = data if (capture_body or not data) else "[REDACTED]"
135+
if not capture_body:
136+
result["body"] = "[REDACTED]"
137+
else:
138+
content_type = request.META.get("CONTENT_TYPE")
139+
if content_type == "application/x-www-form-urlencoded":
140+
data = compat.multidict_to_dict(request.POST)
141+
elif content_type and content_type.startswith("multipart/form-data"):
142+
data = compat.multidict_to_dict(request.POST)
143+
if request.FILES:
144+
data["_files"] = {field: file.name for field, file in compat.iteritems(request.FILES)}
145+
else:
146+
try:
147+
data = request.body
148+
except Exception as e:
149+
self.logger.debug("Can't capture request body: %s", compat.text_type(e))
150+
data = "<unavailable>"
151+
if data is not None:
152+
result["body"] = data
149153

150154
if hasattr(request, "get_raw_uri"):
151155
# added in Django 1.9

elasticapm/contrib/flask/utils.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,27 @@ def get_data_from_request(request, config, event_type):
4646
if config.capture_headers:
4747
result["headers"] = dict(get_headers(request.environ))
4848
if request.method in constants.HTTP_WITH_BODY:
49-
body = None
50-
if request.content_type == "application/x-www-form-urlencoded":
51-
body = compat.multidict_to_dict(request.form)
52-
elif request.content_type and request.content_type.startswith("multipart/form-data"):
53-
body = compat.multidict_to_dict(request.form)
54-
if request.files:
55-
body["_files"] = {
56-
field: val[0].filename if len(val) == 1 else [f.filename for f in val]
57-
for field, val in compat.iterlists(request.files)
58-
}
49+
if config.capture_body not in ("all", event_type):
50+
result["body"] = "[REDACTED]"
5951
else:
60-
try:
61-
body = request.get_data(as_text=True)
62-
except ClientDisconnected:
63-
pass
52+
body = None
53+
if request.content_type == "application/x-www-form-urlencoded":
54+
body = compat.multidict_to_dict(request.form)
55+
elif request.content_type and request.content_type.startswith("multipart/form-data"):
56+
body = compat.multidict_to_dict(request.form)
57+
if request.files:
58+
body["_files"] = {
59+
field: val[0].filename if len(val) == 1 else [f.filename for f in val]
60+
for field, val in compat.iterlists(request.files)
61+
}
62+
else:
63+
try:
64+
body = request.get_data(as_text=True)
65+
except ClientDisconnected:
66+
pass
6467

65-
if body is not None:
66-
result["body"] = body if config.capture_body in ("all", event_type) else "[REDACTED]"
68+
if body is not None:
69+
result["body"] = body
6770

6871
result["url"] = get_url_dict(request.url)
6972
return result

elasticapm/contrib/starlette/utils.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,20 @@ async def get_data_from_request(request: Request, config: Config, event_type: st
5858
result["headers"] = dict(request.headers)
5959

6060
if request.method in constants.HTTP_WITH_BODY:
61-
body = None
62-
try:
63-
body = await get_body(request)
64-
if request.headers.get("content-type") == "application/x-www-form-urlencoded":
65-
body = await query_params_to_dict(body)
66-
else:
67-
body = json.loads(body)
68-
except Exception:
69-
pass
70-
if body is not None:
71-
result["body"] = body if config.capture_body in ("all", event_type) else "[REDACTED]"
61+
if config.capture_body not in ("all", event_type):
62+
result["body"] = "[REDACTED]"
63+
else:
64+
body = None
65+
try:
66+
body = await get_body(request)
67+
if request.headers.get("content-type") == "application/x-www-form-urlencoded":
68+
body = await query_params_to_dict(body)
69+
else:
70+
body = json.loads(body)
71+
except Exception:
72+
pass
73+
if body is not None:
74+
result["body"] = body
7275

7376
result["url"] = get_url_dict(str(request.url))
7477

tests/contrib/django/django_tests.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ def test_post_raw_data(django_elasticapm_client):
613613
assert request["body"] == "[REDACTED]"
614614

615615

616+
@pytest.mark.parametrize("django_elasticapm_client", [{"capture_body": "errors"}], indirect=True)
616617
def test_post_read_error_logging(django_elasticapm_client, caplog, rf):
617618
request = rf.post("/test", data="{}", content_type="application/json")
618619

@@ -1426,8 +1427,10 @@ def test_capture_empty_body(client, django_elasticapm_client):
14261427
with pytest.raises(MyException):
14271428
client.post(reverse("elasticapm-raise-exc"), data={})
14281429
error = django_elasticapm_client.events[ERROR][0]
1429-
# body should be empty no matter if we capture it or not
1430-
assert error["context"]["request"]["body"] == {}
1430+
if django_elasticapm_client.config.capture_body not in ("error", "all"):
1431+
assert error["context"]["request"]["body"] == "[REDACTED]"
1432+
else:
1433+
assert error["context"]["request"]["body"] == {}
14311434

14321435

14331436
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)