API в Flask - возвращает JSON, но исключения HTML нарушают мой клиент JSON

исключения, возвращаемые в HTML, разбивают мой клиент JSON. Я хочу изменить этот вывод.

Подробнее: у меня есть функция просмотра, которая является конечной точкой этого приложения api.

Как вы можете видеть, эта функция возвращает результат в json.

@app.route('/route1')
def api_route1():
    if user_id in request.args: 
        k1 = request.args['user_id']
        return flask.jsonify(recs=some_function(k1))
    else:
        return "no valid user_id supplied"

Проблема, необработанное исключение находится в HTML, например,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
    Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>TypeError: 'NoneType' object is not iterable // Werkzeug Debugger</title>
        <link rel="stylesheet" 
            href="?__debugger__=yes&amp;cmd=resource&amp;f=style.css" 
            type="text/css">

Это нарушает мой json-клиент. Формат HTML явно по умолчанию, но я не знаю, как отказаться от него и указать jsonified exceptions (и в идеале jsonify все возвращенные даже заголовки).

Я подозреваю, что мне нужно где-то в отличной документации по фляге, но я не могу ее найти.

Ответ 1

Вы должны определить HTTP обработчики ошибок в колбе.

Простой обработчик JSON returing 404 может выглядеть примерно так:

@app.errorhandler(404)
def page_not_found(e):
    return flask.jsonify(error=404, text=str(e)), 404

При этом вы сможете проверить наличие data.error на клиенте, и, если оно существует, вы можете получить текст ошибки с data.text (ошибка, переданная как e, равна werkzeug.exceptions.NotFound, строковое представление которой равно "404").: Не обнаружена").

Ответ 2

Обеспечение доступности трассировки для клиента JSON может раскрыть конфиденциальную информацию.

Мой совет:

  • выключить отладку
  • установите инструмент агрегации журналов, например sentry
  • сделать страницу с ошибкой 500 для этого приложения, вернуть общую ошибку в формате json

Страница 500 может выглядеть следующим образом:

{ "error": "500 - internal server error" }

Ответ 3

Код ниже должен сделать трюк. Таким образом, идея состоит в том, чтобы поймать любое исключение, которое могло быть поднято, получить детали исключения, отформатированные как строка, используя модуль трассировки, а затем вернуть это как действительный json. Я бы рекомендовал разместить кучу исключающих операторов с основными типами ошибок, которые вы ожидаете, и более читаемым сообщением об ошибке. Тогда у вас может быть один последний, кроме как поймать все на случай, если произойдет что-то странное и неожиданное.

import traceback

@app.route('/route1')
def api_route1():
    if user_id in request.args: 
        try:
            k1 = request.args['user_id']
            return flask.jsonify(recs=some_function(k1))
        except:
            return flask.jsonify(exception=traceback.format_exc())
    else:
        return flask.jsonify(exception="no valid user_id supplied")

Ответ 4

Вы пробовали http://flask.pocoo.org/docs/patterns/errorpages/ для пользовательских страниц ошибок? Просто верните JSON с этим для ожидаемых кодов ошибок.