首页 > 解决方案 > Flask: Unknown error although 200 response code is returned

问题描述

I have created a simple Flask RESTful API with a single function used to service GET requests and which expects several URL parameters:

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)

When I send a GET request to the endpoint with or without parameters I get none of the expected behavior -- if good parameters are included in the GET request then I expect to see a log message in the console, and if none of the required parameters are present then I expect to get some sort of error as a result. Instead, I get what appear to be 200 response codes in the console and simply the phrase "Unknown Error" in the main browser window.

For example, if I enter the following URL without the expected parameters into my Chrome browser's address bar: http://127.0.0.1:5000/abc I then see this in the console:

2019-05-28  17:42:14 INFO  127.0.0.1 - - [28/May/2019 17:42:14] "GET /abc HTTP/1.1" 200 -

My assumption is that the above should throw an error of some sort indicating the missing URL parameters.

If I enter the following URL with the expected parameters into my Chrome browser's address bar: http://127.0.0.1:5000/abc?rtsp=rtsp://user:passwd@171.25.14.15:554&start=1559076593&duration=10&bucket=testbucket&prefix=test. I then see this in the console:

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 -

My assumption is that the above should cause the logger to print the information message to the console as is defined in the Abc.get function.

If I use curl at the command line then I get the following result:

$ 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>

Whi is this going amiss, and how I can achieve the expected behavior? (My intention is to use this approach to pass arguments to a more realistic GET handler that will launch a video recording function when the request is received, the above has been simplified as much as possible for clarity.)

I am using Flask 1.0.3, Flask-Restful 0.3.6, and Webargs 5.3.1 in an Anaconda environment (Python 3.7) on Ubuntu 18.04.

标签: flask

解决方案


我已经设法使用不依赖的更简单的代码来获得预期的行为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)

推荐阅读