Проверка правил колб и арматуры - PullRequest
0 голосов
/ 21 ноября 2018

Мне нужно проверить правило Flask в REST API, построенном с использованием Flask-Rebar.Я пробовал следующий метод:

@registry.handles(
    rule='/horses/<int:horse_id>',
    method='GET',
    marshal_schema=GetHorseByIdSchema()
)
def getHorseById(horse_id):
    return {"horse_id": horse_id}

Это использует синтаксис <int:my_var>, как указано здесь .При вводе целочисленного значения в качестве horse_id все работает правильно.Проблема возникает из-за ввода нецелого значения, например a;это выдает код состояния 404 Not Found, когда я ожидал 400 Bad Request.

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

Спасибо, Адам

1 Ответ

0 голосов
/ 27 декабря 2018

Вот как ведет себя Flask / Werkzeug, так что это немного вне контроля Flask-Rebar.То есть следующее также вернет 404 для /horses/a:

app = Flask(__name__)

@app.route('/horses/<int:horse_id>')
def getHorseById(horse_id):
    return str(horse_id)

С этим вот несколько обходных путей:

(1) Конвертер пользовательских URL: http://flask.pocoo.org/docs/1.0/api/#flask.Flask.url_map

Это будет выглядеть примерно так:

import flask
from werkzeug.routing import BaseConverter

class StrictIntegerConverter(BaseConverter):
    def to_python(self, value):
        try:
            return int(value)
        except ValueError:
            flask.abort(400)

app = flask.Flask(__name__)
app.url_map.converters['strict_integer'] = StrictIntegerConverter


@registry.handles(
    rule='/horses/<strict_integer:horse_id>',
    method='GET',
    marshal_schema=GetHorseByIdSchema()
)
def getHorseById(horse_id):
    return {'horse_id': horse_id}

Однако маршрутизация выполняется вне контекста приложения, поэтому мы не можем использовать ни flask.jsonify, ни ошибки Flask-Rebar, чтобы вызвать хороший JSONошибки.

(2) Проверьте тип внутри функции обработчика

from flask_rebar.errors import BadRequest

@registry.handles(
    rule='/horses/<horse_id>',
    method='GET',
    marshal_schema=GetHorseByIdSchema()
)
def getHorseById(horse_id):
    try:
        horse_id = int(horse_id)
    except ValueError:
        raise BadRequest('horse_id must be an integer')
    return {'horse_id': horse_id}

Это немного менее элегантно, но работает.Документ Swagger по умолчанию будет использовать строковый тип для параметра horse_id, но мы также можем обойти это:

from werkzeug.routing import UnicodeConverter

class StrDocumentedAsIntConverter(UnicodeConverter):
    pass

app.url_map.converters['str_documented_as_int'] = StrDocumentedAsIntConverter
registry.swagger_generator.register_flask_converter_to_swagger_type('str_documented_as_int', 'int')

@registry.handles(rule='/horses/<str_documented_as_int:horse_id>')
...

(3) Принять поведение Flask / Werkzeug

В зависимости от того, насколько сильно вам нужно 400 вместо 404, наиболее практично было бы ничего не делать и просто поддаваться тому, как это делают Flask / Werkzeug.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...