簡體   English   中英

如何在 Flask 上返回 400(錯誤請求)?

[英]How to return 400 (Bad Request) on Flask?

我創建了一個簡單的 flask 應用程序,我正在讀取來自 python 的響應:

response = requests.post(url,data=json.dumps(data), headers=headers ) 
data = json.loads(response.text)

現在我的問題是,在某些情況下,我想返回 400 或 500 消息響應。 到目前為止,我正在這樣做:

abort(400, 'Record not found') 
#or 
abort(500, 'Some error...') 

這確實會在終端上打印消息:

在此處輸入圖像描述

但在 API 響應中,我不斷收到 500 錯誤響應:

在此處輸入圖像描述

代碼結構如下:

|--my_app
   |--server.py
   |--main.py
   |--swagger.yml

server.py有這個代碼的地方:

from flask import render_template
import connexion
# Create the application instance
app = connexion.App(__name__, specification_dir="./")
# read the swagger.yml file to configure the endpoints
app.add_api("swagger.yml")
# Create a URL route in our application for "/"
@app.route("/")
def home():
    """
    This function just responds to the browser URL
    localhost:5000/

    :return:        the rendered template "home.html"
    """
    return render_template("home.html")
if __name__ == "__main__":
    app.run(host="0.0.0.0", port="33")

main.py包含我用於 API 端點的所有 function。

例如:

def my_funct():
   abort(400, 'Record not found') 

調用my_funct時,我在終端上打印了Record not found ,但 API 本身的響應中沒有,我總是收到 500 消息錯誤。

您有多種選擇:

最基本的:

@app.route('/')
def index():
    return "Record not found", 400

如果要訪問標頭,可以獲取響應對象:

@app.route('/')
def index():
    resp = make_response("Record not found", 400)
    resp.headers['X-Something'] = 'A value'
    return resp

或者你可以讓它更明確,而不只是返回一個數字,而是返回一個狀態代碼對象

from flask_api import status

@app.route('/')
def index():
    return "Record not found", status.HTTP_400_BAD_REQUEST

進一步閱讀:

您可以在此處閱讀有關前兩個的更多信息: 關於響應(Flask 快速入門)
第三個:狀態代碼(Flask API 指南)

我喜歡使用flask.Response類:

from flask import Response


@app.route("/")
def index():
    return Response(
        "The response body goes here",
        status=400,
    )

flask.abort是圍繞werkzeug.exceptions.abort的包裝,它實際上只是一個幫助方法,可以更輕松地引發 HTTP 異常。 在大多數情況下這很好,但是對於restful API,我認為明確返回響應可能更好。

這是我多年前編寫的 Flask 應用程序的一些片段。 它有一個 400 響應的示例

import werkzeug
from flask import Flask, Response, json
from flask_restplus import reqparse, Api, Resource, abort
from flask_restful import request
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('address_to_score', type=werkzeug.datastructures.FileStorage, location='files')

class MissingColumnException(Exception):
    pass

class InvalidDateFormatException(Exception):
    pass

@api.route('/project')
class project(Resource):

    @api.expect(parser)
    @api.response(200, 'Success')
    @api.response(400, 'Validation Error')
    def post(self):
        """
        Takes in an excel file of addresses and outputs a JSON with scores and rankings.
        """
        try:
            df, input_trees, needed_zones = data.parse_incoming_file(request)

        except MissingColumnException as e:
            abort(400, 'Excel File Missing Mandatory Column(s):', columns=str(e))

        except Exception as e:
            abort(400, str(e))

        project_trees = data.load_needed_trees(needed_zones, settings['directories']['current_tree_folder'])

        df = data.multiprocess_query(df, input_trees, project_trees)
        df = data.score_locations(df)
        df = data.rank_locations(df)
        df = data.replace_null(df)
        output_file = df.to_dict('index')
        resp = Response(json.dumps(output_file), mimetype='application/json')
        resp.status_code = 200

    return resp

@api.route('/project/health')
class projectHealth(Resource):

    @api.response(200, 'Success')
    def get(self):
        """
        Returns the status of the server if it's still running.
        """
        resp = Response(json.dumps('OK'), mimetype='application/json')
        resp.status_code = 200

    return resp

您可以返回一個元組,第二個元素是狀態(400 或 500)。

from flask import Flask
app = Flask(__name__)


@app.route('/')
def hello():
    return "Record not found", 400

if __name__ == '__main__':
    app.run()

從python調用API的例子:

import requests

response = requests.get('http://127.0.0.1:5000/')

response.text
# 'This is a bad request!'

response.status_code
# 400

我認為您正確使用了abort()函數。 我懷疑這里的問題是錯誤處理程序正在捕獲 400 錯誤,然后出錯導致 500 錯誤。 有關燒瓶錯誤處理的更多信息,請參見此處

例如,以下內容會將 400 更改為 500 錯誤:

@app.errorhandler(400)
def handle_400_error(e):
    raise Exception("Unhandled Exception")

如果你沒有做任何錯誤處理,它可能來自connexion框架,盡管我不熟悉這個框架。

您可以簡單地使用@app.errorhandler裝飾器。

例子:

 @app.errorhandler(400)
    def your_function():
        return 'your custom text', 400

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM