Skip to content

Commit

Permalink
Doesn"t cut request body with size >= 10000 (#1635)
Browse files Browse the repository at this point in the history
* feat: doesn"t cut request body with size >= 10000

last push to master has errors, if body size more than 10000, it writes 10000 message to elastic and call await self.app(scope, receive, wrapped_send) with same receive and invalid body, I separate receivers and now, if request has body more than 10000 -> it will send to elastic only 10000 and continue handle as normal request without cutting

* CHANGELOG

* Add test

Co-authored-by: Colton Myers <colton@myers.fm>
  • Loading branch information
mukhamux and Colton Myers committed Sep 19, 2022
1 parent 77c2c0d commit d529e29
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Expand Up @@ -40,6 +40,7 @@ endif::[]
===== Bug fixes
* Fix Django's `manage.py check` when agent is disabled {pull}1632[#1632]
* Fix an issue with long body truncation for Starlette {pull}1635[#1635]
[[release-notes-6.x]]
Expand Down
19 changes: 15 additions & 4 deletions elasticapm/contrib/starlette/__init__.py
Expand Up @@ -146,6 +146,9 @@ async def wrapped_send(message):
elasticapm.set_transaction_result(result, override=False)
await send(message)

_mocked_receive = None
_request_receive = None

if self.client.config.capture_body != "off":

# When we consume the body from receive, we replace the streaming
Expand All @@ -165,17 +168,25 @@ async def wrapped_send(message):
if message["type"] == "http.disconnect":
break

joined_body = b"".join(body)

async def mocked_receive() -> Message:
await asyncio.sleep(0)
return {"type": "http.request", "body": long_field(b"".join(body))}
return {"type": "http.request", "body": long_field(joined_body)}

_mocked_receive = mocked_receive

async def request_receive() -> Message:
await asyncio.sleep(0)
return {"type": "http.request", "body": joined_body}

receive = mocked_receive
_request_receive = request_receive

request = Request(scope, receive=receive)
request = Request(scope, receive=_mocked_receive or receive)
await self._request_started(request)

try:
await self.app(scope, receive, wrapped_send)
await self.app(scope, _request_receive or receive, wrapped_send)
elasticapm.set_transaction_outcome(constants.OUTCOME.SUCCESS, override=False)
except Exception:
await self.capture_exception(
Expand Down
5 changes: 3 additions & 2 deletions tests/contrib/asyncio/starlette_tests.py
Expand Up @@ -67,10 +67,10 @@ def app(elasticapm_client):

@app.route("/", methods=["GET", "POST"])
async def hi(request):
await request.body()
body = await request.body()
with async_capture_span("test"):
pass
return PlainTextResponse("ok")
return PlainTextResponse(str(len(body)))

@app.route("/hi/{name}", methods=["GET"])
async def hi_name(request):
Expand Down Expand Up @@ -449,6 +449,7 @@ def test_long_body(app, elasticapm_client):
transaction = elasticapm_client.events[constants.TRANSACTION][0]
request = transaction["context"]["request"]
assert request["body"] == "foo=" + "b" * 9993 + "..."
assert response.text == "10004"


def test_static_files_only_file_notfound(app_static_files_only, elasticapm_client):
Expand Down

0 comments on commit d529e29

Please sign in to comment.