我创建了一个简单的Flask RESTful API,该API具有用于服务GET请求的单个函数,并且需要多个URL参数:
import logging
from flask import Flask
from flask_restful import Api, Resource
from webargs import fields
from webargs.flaskparser import abort, parser, use_args
# initialize the Flask application and API
app = Flask(__name__)
api = Api(app)
# ------------------------------------------------------------------------------
# set up a basic, global logger object which will write to the console
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
_logger = logging.getLogger(__name__)
# ------------------------------------------------------------------------------
class Abc(Resource):
abc_args = {"rtsp": fields.Url(required=True),
"start": fields.Integer(required=True),
"duration": fields.Integer(required=True),
"bucket": fields.String(required=True),
"prefix": fields.String(missing="")}
@use_args(abc_args)
def get(self, args) -> (str, int):
_logger.info("Recording video clip with the following parameters:\n"
f"\tRTSP URL: {args['rtsp']}"
f"\tStart seconds: {args['start']}"
f"\tDuration seconds: {args['duration']}"
f"\tS3 bucket: {args['bucket']}"
f"\tS3 key prefix: {args['prefix']}")
return "OK", 200
# ------------------------------------------------------------------------------
# This error handler is necessary for usage with Flask-RESTful
@parser.error_handler
def handle_request_parsing_error(err, req, schema, error_status_code, error_headers):
"""
webargs error handler that uses Flask-RESTful's abort function to return
a JSON error response to the client.
"""
abort(error_status_code, errors=err.messages)
# ------------------------------------------------------------------------------
if __name__ == '__main__':
api.add_resource(Abc, "/abc", endpoint="abc")
app.run(debug=True)
当我将GET请求发送到带有或不带有参数的端点时,我不会得到预期的行为-如果GET请求中包含良好的参数,那么我希望在控制台中看到一条日志消息,并且如果没有存在必需的参数,那么我期望得到某种错误。取而代之的是,我在控制台中看到的似乎是200个响应代码,而在主浏览器窗口中仅得到了短语“ Unknown Error”。
例如,如果我在Chrome浏览器的地址栏中输入以下URL,但未输入预期的参数:http://127.0.0.1:5000/abc
然后,我在控制台中看到了这一点:
2019-05-28 17:42:14 INFO 127.0.0.1 - - [28/May/2019 17:42:14] "GET /abc HTTP/1.1" 200 -
我的假设是,上面的代码应该抛出某种错误,指示缺少URL参数。
如果我在Chrome浏览器的地址栏中输入以下带有预期参数的URL:http://127.0.0.1:5000/abc?rtsp=rtsp://user:passwd@171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test.
然后,我在控制台中看到了这一点:
2019-05-28 17:45:31 INFO 127.0.0.1 - - [28/May/2019 17:45:31] "GET /abc?rtsp=rtsp://user:passwd@171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test. HTTP/1.1" 200 -
我的假设是,以上所述应导致记录器按照Abc.get
函数中的定义将信息消息打印到控制台。
如果我在命令行中使用curl
,则会得到以下结果:
$ curl "http://127.0.0.1:5000/abc?rtsp=rtsp://user:passwd@171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test."
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>None Unknown Error</title>
<h1>Unknown Error</h1>
<p></p>
谁能解释为什么这会出错,和/或我如何实现预期的行为? (我的目的是使用这种方法将参数传递给更现实的GET处理程序,该处理程序将在收到请求时启动视频录制功能,为清楚起见,已对上述内容进行了尽可能的简化。)
我在Ubuntu 18.04上的Anaconda环境(Python 3.7)中使用Flask 1.0.3,Flask-Restful 0.3.6和Webargs 5.3.1。
在此先感谢您的任何意见或建议。
答案 0 :(得分:0)
我已经使用不依赖flask_restful
的简单代码设法获得了预期的行为。见下文:
import logging
from flask import Flask, request
# initialize the Flask application
app = Flask(__name__)
# ------------------------------------------------------------------------------
# set up a basic, global logger object which will write to the console
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
_logger = logging.getLogger(__name__)
# ------------------------------------------------------------------------------
@app.route('/clip', methods=['GET'])
def record_and_store_clip():
message = "Recording video clip with the following parameters:\n" + \
f"\tRTSP URL: {request.args.get('rtsp')}\n" + \
f"\tStart seconds: {request.args.get('start')}\n" + \
f"\tDuration seconds: {request.args.get('duration')}\n" + \
f"\tS3 bucket: {request.args.get('bucket')}\n" + \
f"\tS3 key prefix: {request.args.get('prefix')}\n"
_logger.info(message)
return message
# ------------------------------------------------------------------------------
if __name__ == '__main__':
app.run(debug=True)