烧瓶:尽管返回200个响应代码,但未知错误

时间:2019-05-28 21:59:26

标签: flask

我创建了一个简单的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。

在此先感谢您的任何意见或建议。

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)