Description
Hi,
I set up correctly an APM Agent in Flask, and now I'm facing an issue in another project that uses FlaskAPI.
As it is, the API returns an "Internal Server Error" because, when the agent retrieves the POST body, it crashes:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1816, in full_dispatch_request
return self.finalize_request(rv)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1834, in finalize_request
request_finished.send(self, response=response)
File "/usr/local/lib/python3.6/site-packages/blinker/base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "/usr/local/lib/python3.6/site-packages/blinker/base.py", line 267, in <listcomp>
for receiver in self.receivers_for(sender)]
File "/usr/local/lib/python3.6/site-packages/elasticapm/contrib/flask/__init__.py", line 145, in request_finished
"request",
File "/usr/local/lib/python3.6/site-packages/elasticapm/traces.py", line 333, in set_context
data = data()
File "/usr/local/lib/python3.6/site-packages/elasticapm/contrib/flask/__init__.py", line 143, in <lambda>
request, capture_body=self.client.config.capture_body in ("transactions", "all")
File "/usr/local/lib/python3.6/site-packages/elasticapm/contrib/flask/utils.py", line 29, in get_data_from_request
body = request.data
File "/usr/local/lib/python3.6/site-packages/werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/local/lib/python3.6/site-packages/flask_api/request.py", line 24, in data
self._parse()
File "/usr/local/lib/python3.6/site-packages/flask_api/request.py", line 53, in _parse
ret = parser.parse(self.stream, media_type, **options)
File "/usr/local/lib/python3.6/site-packages/flask_api/parsers.py", line 32, in parse
raise exceptions.ParseError(msg)
flask_api.exceptions.ParseError: JSON parse error - Expecting value: line 1 column 1 (char 0)
In this case, when /usr/local/lib/python3.6/site-packages/elasticapm/contrib/flask/utils.py (line 29) retrieves the body, it uses request.data
.
Instead of using directly the data
attribute, using request.get_data()
makes it work and the json body is correctly retrieved and parsed. I tried it on the project in which there's only Flask and not FlaskAPI, and it works like a charm.
Another option would be to be less precise when catching potentiel exceptions, to make sure the request won't return an internal server error. For now, it's only ClientDisconnected
.
I'm using:
- python 3.7
- Flask==1.0.2
- Flask-API==1.0
Thanks in advance.
ph