我需要在使用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}
这使用here指定的<int:my_var>
语法。当输入整数值作为horse_id
时,一切正常。问题来自输入非整数值,即a
;当我期望404 Not Found
时,它将抛出400 Bad Request
状态代码。
我认为我无法使用任何编组模式进行此操作,因此我不确定下一步该怎么做,我们将提供任何帮助。
谢谢, 亚当
答案 0 :(得分:1)
这是Flask / Werkzeug的行为方式,因此有点超出Flask-Rebar的控制范围。也就是说,以下代码还将返回/horses/a
的404:
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的工作方式,这可能是最实际的。