如何使用 Flask-return 响应 400 Bad Request-RESTful.RequestParser?
How to return a 400 Bad Request response using Flask-RESTful.RequestParser?
我正在使用 Flask 和 Flask-RESTful 创建一个 API。我希望使用 flask_restful.reqparse.RequestParser()
解析传入请求的主体。在收到不正确的 JSON 后,我想 return 一个 400 Bad Request 响应。但是,我的应用程序 returning 了 500 Internal Server Error 响应。我认为 RequestParser()
应该自动处理这些响应?谁能解释一下出了什么问题?
下面是 API Resource
的代码
from flask_restful import Resource, reqparse
class Foo(Resource):
parser = reqparse.RequestParser()
parser.add_argument("foo",
type=int,
required=True,
action='append',
help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}"
)
def get(self):
data = self.parser.parse_args(strict=True)
return {'bar': data['foo']}
当我向 API 发送一个正文为 {"err": [3, 4, 1]}
的 GET 请求时,我收到以下 500 内部服务器错误响应:
{"message": "Internal Server Error"}
而不是我在 help
参数中指定的消息。在我的日志中,我还收到以下错误消息:
KeyError: "'foo'"
我知道我可以将 data = self.parser.parse_args(strict=True)
包装在 try/except KeyError 子句中并自己处理不正确的 JSON,但我认为 Flask-RESTful 会那样做为了我?我还能尝试什么?
通过定义将传递给 RequestParser
构造函数的 APIArgument
class,您可以定义自己的自定义响应。您还需要将 bundle_errors = True
传递给构造函数并通过将应用程序配置键“BUNDLE_ERRORS”设置为 True[=21 来配置 flask =]
请参阅请求解析的 error handling。
import json
from flask import Flask, Response, abort
from flask_restful import Api, Resource, reqparse
from flask_restful.reqparse import Argument
app = Flask(__name__)
app.config["BUNDLE_ERRORS"] = True
api = Api(app)
class APIArgument(Argument):
def __init__(self, *args, **kwargs):
super(APIArgument, self).__init__(*args, **kwargs)
def handle_validation_error(self, error, bundle_errors):
help_str = "(%s) " % self.help if self.help else ""
msg = "[%s]: %s%s" % (self.name, help_str, str(error))
res = Response(
json.dumps({"message": msg, "code": 400, "status": "FAIL"}),
mimetype="application/json",
status=400,
)
return abort(res)
class Foo(Resource):
parser = reqparse.RequestParser(argument_class=APIArgument, bundle_errors=True)
parser.add_argument(
"foo",
type=int,
action="append",
required=True,
help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}",
)
def get(self):
data = self.parser.parse_args(strict=True)
return {'bar': data['foo']}
api.add_resource(Foo, '/')
if __name__ == "__main__":
app.run(port=9000, debug=True)
对于那些不想处理样板代码的人,这也适用:
通过将解析器代码移动到 get() 路由中,将使用 flask-restful 提供的默认 handle_validation_error 函数(我猜):
class Foo(Resource):
def get(self):
parser = reqparse.RequestParser()
parser.add_argument('foo', required=True, action="append", help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}",
data = parser.parse_args()
print(data.get("foo")
# this code won't be reached, because the parser aborts the request early if foo is missing
return {'bar': data['foo']}
这意味着您必须为每个方法提供一个单独的解析器,但我认为这通常是个好主意,而不是在路由本身中为所有方法定义它。 flask-restful 可能不打算这样做,这就是为什么它不能开箱即用的原因。
另外:请记住,如果请求来自浏览器,GET 请求不能有 json 正文,这只有在不涉及浏览器的情况下才有可能!我通常不建议这样做,因为它不是 standard-compatible.
我正在使用 Flask 和 Flask-RESTful 创建一个 API。我希望使用 flask_restful.reqparse.RequestParser()
解析传入请求的主体。在收到不正确的 JSON 后,我想 return 一个 400 Bad Request 响应。但是,我的应用程序 returning 了 500 Internal Server Error 响应。我认为 RequestParser()
应该自动处理这些响应?谁能解释一下出了什么问题?
下面是 API Resource
from flask_restful import Resource, reqparse
class Foo(Resource):
parser = reqparse.RequestParser()
parser.add_argument("foo",
type=int,
required=True,
action='append',
help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}"
)
def get(self):
data = self.parser.parse_args(strict=True)
return {'bar': data['foo']}
当我向 API 发送一个正文为 {"err": [3, 4, 1]}
的 GET 请求时,我收到以下 500 内部服务器错误响应:
{"message": "Internal Server Error"}
而不是我在 help
参数中指定的消息。在我的日志中,我还收到以下错误消息:
KeyError: "'foo'"
我知道我可以将 data = self.parser.parse_args(strict=True)
包装在 try/except KeyError 子句中并自己处理不正确的 JSON,但我认为 Flask-RESTful 会那样做为了我?我还能尝试什么?
通过定义将传递给 RequestParser
构造函数的 APIArgument
class,您可以定义自己的自定义响应。您还需要将 bundle_errors = True
传递给构造函数并通过将应用程序配置键“BUNDLE_ERRORS”设置为 True[=21 来配置 flask =]
请参阅请求解析的 error handling。
import json
from flask import Flask, Response, abort
from flask_restful import Api, Resource, reqparse
from flask_restful.reqparse import Argument
app = Flask(__name__)
app.config["BUNDLE_ERRORS"] = True
api = Api(app)
class APIArgument(Argument):
def __init__(self, *args, **kwargs):
super(APIArgument, self).__init__(*args, **kwargs)
def handle_validation_error(self, error, bundle_errors):
help_str = "(%s) " % self.help if self.help else ""
msg = "[%s]: %s%s" % (self.name, help_str, str(error))
res = Response(
json.dumps({"message": msg, "code": 400, "status": "FAIL"}),
mimetype="application/json",
status=400,
)
return abort(res)
class Foo(Resource):
parser = reqparse.RequestParser(argument_class=APIArgument, bundle_errors=True)
parser.add_argument(
"foo",
type=int,
action="append",
required=True,
help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}",
)
def get(self):
data = self.parser.parse_args(strict=True)
return {'bar': data['foo']}
api.add_resource(Foo, '/')
if __name__ == "__main__":
app.run(port=9000, debug=True)
对于那些不想处理样板代码的人,这也适用:
通过将解析器代码移动到 get() 路由中,将使用 flask-restful 提供的默认 handle_validation_error 函数(我猜):
class Foo(Resource):
def get(self):
parser = reqparse.RequestParser()
parser.add_argument('foo', required=True, action="append", help="Request body must contain a 'foo' key which comprises a list of IDs, e.g. {'foo': [44, 3213, 532, 4312]}",
data = parser.parse_args()
print(data.get("foo")
# this code won't be reached, because the parser aborts the request early if foo is missing
return {'bar': data['foo']}
这意味着您必须为每个方法提供一个单独的解析器,但我认为这通常是个好主意,而不是在路由本身中为所有方法定义它。 flask-restful 可能不打算这样做,这就是为什么它不能开箱即用的原因。
另外:请记住,如果请求来自浏览器,GET 请求不能有 json 正文,这只有在不涉及浏览器的情况下才有可能!我通常不建议这样做,因为它不是 standard-compatible.