我正在使用 Flask 和 Flask-RESTful 創建一個 API。我希望使用flask_restful.reqparse.RequestParser(). 收到不正確的 JSON 后,我想回傳 400 Bad Request 回應。但是,我的應用程式改為回傳 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 發送 GET 請求時,{"err": [3, 4, 1]}我收到以下 500 Internal Server Error 回應:
{"message": "Internal Server Error"}
而不是我在help引數中指定的訊息。在我的日志中,我還收到以下錯誤訊息:
KeyError: "'foo'"
I know I could wrap the data = self.parser.parse_args(strict=True) in a try/except KeyError clause and handle the incorrect JSON myself, but I thought that Flask-RESTful would do that for me? What else could I try?
uj5u.com熱心網友回復:
通過定義APIArgument將傳遞給RequestParser建構式的類,您可以定義自己的自定義回應。您還需要通過bundle_errors = True將應用程式配置鍵“ BUNDLE_ERRORS ”設定為True將 傳遞給建構式并配置燒瓶
請參閱請求決議的錯誤處理。
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)
uj5u.com熱心網友回復:
對于那些不想處理樣板代碼的人,這也適用:
通過將決議器代碼移動到 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 主體,這只有在不涉及瀏覽器的情況下才有可能!我通常不建議這樣做,因為它不符合標準。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/456115.html
