jpavs
jpavs

Reputation: 658

Flask returning a 200 code when I expect a 500

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

Answers (1)

iurisilvio
iurisilvio

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

Related Questions