我的解決方案是擴展Flask-RESTful Api
clas並實現我的自定義錯誤處理程序。該official documentation explains a little bit about extending,但沒有進入足夠的細節。
自定義錯誤消息
在我的應用程序的所有錯誤是在這個結構中
class InvalidParameter(Exception):
status_code = 400
def __init__(self, message, status_code=None, resource=None,
field=None, code=None, stack_trace=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.resource = resource
self.field = field
self.code = code
self.stack_trace = stack_trace
def to_dict(self):
rv = {}
errors = {}
rv['message'] = self.message
errors['resource'] = self.resource
errors['field'] = self.field
errors['code'] = self.code
errors['stack_trace'] = self.stack_trace
rv['errors'] = errors
return rv
這是默認瓶的RESTful返回
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
輸出應該是JSON,在這種格式
{
"message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. You have requested this URI [/projects/1asd] but did you mean /projects/<int:project_id> or /projects or /project/new ?",
"errors": {
"resource": null,
"field": null,
"code": "invalid_url",
"stack_trace": null
}
}
解決方案
擴展Api
類,並覆蓋了404
錯誤
class CustomApi(Api):
def handle_error(self, e):
code = getattr(e, 'code', 404)
if code == 404:
response_dict = Api.handle_error(self, e).__dict__
resp_message = response_dict['response'][0]
error_message = re.sub(r'.*"(.*)".*', r'\1', resp_message.decode('utf-8'), flags=re.DOTALL)
err = InvalidParameter(error_message, stack_trace=None,
resource=None, code="invalid_url", field=None)
return self.make_response(err.to_dict(), 404) #{'message': "something", 'error': {'sub1': 'val1'}}, 404)
return super(Api, self).handle_error(e)
的handle_error
字典是在這種格式handle_error
方法
{'headers': Headers([('Content-Type', 'application/json'), ('Content-Length', '263')]), '_status_code': 404, '_status': '404 NOT FOUND', 'direct_passthrough': False, '_on_close': [], 'response': [b'{\n "message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again. You have requested this URI [/projects/1asd] but did you mean /projects/<int:project_id> or /projects or /project/new ?"\n}\n']}
我想重新使用'response':'message'
這是生成,但不是默認格式。 message
不是沒有正確JSON格式的,所以我去掉一切,除了爲message
內容,使用此正則表達式
error_message = re.sub(r'.*"(.*)".*', r'\1', resp_message.decode('utf-8'), flags=re.DOTALL)
注意re.DOTALL
需要剝離出來,是由瓶的RESTful加入\n
。
即實際編制JSON響應的代碼是self.make_response(err.to_dict(), 404)
對於所有其他非404錯誤(例如400,500,503),該錯誤只是沿着原來的瓶的RESTful API類通過。
注意,當您創建瓶的應用程序,您需要使用您的自定義API類,並捕獲所有的404錯誤:
app = Flask(__name__)
api = CustomApi(app, catch_all_404s=True)
我的理解,你想用'project_id'工作與'INT '並將請求參數的驗證移動到其他級別(從視圖中)? –
是的,我想確保'project_id'是'int'。如果不是,我想返回自定義的JSON錯誤消息 – hanxue
我以前有同樣的問題。我一直在尋找解決方案。 Flask沒有現代的驗證方式(通過類型轉換)。您可以使用Flask-WTF或RequestParser驗證POST或GET參數。但是這個工具不會將值轉換爲指定的類型。此外,他們對請求參數進行繁瑣的描述。你可以嘗試[this](https://github.com/d-ganchar/flask_request_validator)工具。目前這個庫不支持Flask-RESTful('from box'),但是這是一個小型庫,你可以擴展它。 –