Reputation: 658
I have a Flask API that is a wrapper for a customer service API. I use generators throughout to keep memory overhead low. I noticed the other day that the 3rd party had removed a key from their API, which was causing call_cs_api
to throw an exception. I would expect Flask to throw a 500 error as a result, but it instead returns a 200. So, I changed my generator to handle the exception as you see below (the solution came from here).
However, even with that addition, and with werkzeug acknowledging the 500 error, I still get a 200 returned to me when I curl that endpoint.
Curiously, if I turn on app.run()
and run the program from main instead of through uwsgi, a 500 is returned successfully. So perhaps it's a flask setting I don't know about. Here is the code and some log trace:
First, the class that handles logging in/retrieving data from the 3rd party:
def call_cs_api(self):
req = requests.get(self.url)
resp = json.loads(req.text)
for case in resp['_embedded']['entries']:
case = self.cleanse_data(case)
yield (case, None)
if next_call:
print next_call
try:
print req.headers['Rate-Limit-Remaining']
print req.headers['Rate-Limit-Reset']
if req.headers['Rate-Limit-Remaining'] == 0:
sleep(int(req.headers['X-Rate-Limit-Reset'])+2)
except KeyError, e:
yield (None, e)
self.url = next_call['href']
for call in self.call_cs_api():
yield call
And my Flask api:
from flask import Flask, abort, Response
import cs_api
@application.route('/users', methods = ['GET'])
def users():
api = cs_api.CSApi('users')
def generate():
cases = api.call_cs_api()
for case,e in cases:
if case:
yield json.dumps(case)
if e:
abort(500)
return Response(generate())
@application.errorhandler(500)
def internal_error(error):
return "500 error - Internal Server Exception"
Stack Trace. The last 2 lines show the 500/200 incongruity:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/werkzeug/wsgi.py", line 682, in __next__
return self._next()
File "/usr/local/lib/python2.7/dist-packages/werkzeug/wrappers.py", line 81, in _iter_encoded
for item in iterable:
File "cs_handler.py", line 31, in generate
abort(500)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/exceptions.py", line 576, in __call__
raise self.mapping[code](*args, **kwargs)
werkzeug.exceptions.InternalServerError: 500: Internal Server Error
[pid: 20937|app: 0|req: 1/1] 10.100.100.51 () {38 vars in 463 bytes} [Sat Nov 7 15:25:37 2015] GET /users => generated 53529 bytes in 481 msecs (HTTP/1.1 200) 1 headers in 59 bytes (50 switches on core 0)
Upvotes: 5
Views: 7151
Reputation: 4987
The errorhandler works like a normal view function. If you don't set the response code, the default is 200
.
Return the 500
error code as the second parameter.
@application.errorhandler(500)
def internal_error(error):
return "500 error - Internal Server Exception", 500
Upvotes: 3