首页 > 解决方案 > 如何优雅地终止休息请求

问题描述

如果缺少输入参数,我想终止到达服务器的休息请求而不进行进一步处理。

目前这是实现,我认为这对verify_required_pa​​rams()不是很好。

如果缺少参数,我想终止此请求而不从verify_required_pa​​rams()返回任何值。否则流程应该继续。

在烧瓶服务器上运行它并打开以包含任何新包以获得最佳/优化方法。

请有人为此建议一种优化方法吗?

@app.route('/is_registered', methods=['POST'])
def is_registered():
    _json = request.get_json()
    keys = _json.keys()
    customer = Customer()

    if verify_required_params(['mobile'], keys) is True:
        _mobile = _json['mobile']

        validated = validate_mobile(_mobile)
        registered = customer.find(_mobile)

        if not validated:
            response = get_response('MOBILE_NUMBER_NOT_VALID')
            return jsonify(response)

        if not registered:
            response = get_response('MOBILE_NUMBER_NOT_REGISTERED')
            return jsonify(response)

        response = get_response('MOBILE_NUMBER_REGISTERED')
        return jsonify(response)

    else:
        return verify_required_params(['mobile'], keys)
        


def verify_required_params(required, received):
    required = set(required)
    received = set(received)
    missing = list(sorted(required - received))

    data = {"missing_key(s)": missing}

    # response = app.response_class(
    #     response=json.dumps(data),
    #     status=200,
    #     mimetype='application/json'
    # )

    if missing:
        return jsonify(data)
    return True

标签: python-3.xflaskflask-restful

解决方案


您说它以 RESTful 方式工作,然后您的错误返回 200 OK

在 REST 中,您的 URL 应该对有关您的实体的所有信息进行编码。在您的情况下,您通过他们的电话号码识别客户,并且您正在获取而不是更新有关他们的信息,因此您的端点应该看起来像GET /client/<phonenumber>/registered. 这样一来,请求就无法在不转到不同端点的情况下提供此信息。

简而言之,您的代码将替换为:

@app.route('/client/<mobile>/registered', methods=['GET'])
def is_registered(mobile):
    if not mobile.is_decimal():
        return jsonify({'error': 'mobile is not number'}), 400  # Bad Request
    customer = Customer()
    registered = bool(customer.find(mobile))
    # does it make sense to have a customer who is not registered yet?
    # if not, use:
    if not registered:
        return jsonify({'error': 'client not found'}), 404  # Not Found

    validated = validate_mobile(mobile)
    return jsonify( {'validated': validated, 'registered': registered} )

另外,验证函数最好是装饰器。这样它就会在函数的实际业务逻辑之前被调用。对于检查是否request.get_json()包含正确字段的示例,它的外观如下:

import functools

def requires_fields(fields):
    required_fields = set(fields)

    def wrapper(func):
        @functools.wraps(decorated)
        def decorated(*args, **kwargs):
            current_fields = set(request.get_json().keys())
            missing_fields = required_fields
            if missing_fields:
                return jsonify({'error': 'missing fields', 'fields': list(missing_fields)}), 400  # Bad Request
            resp = func(*args, **kwargs)
            return resp
    return wrapper

# usage:

@app.route('/comment', methods=['POST'])
@requires_fields(['author', 'post_id', 'body'])
def create_comment():
    data = request.get_json()
    id = FoobarDB.insert('comment', author=data['author'], post_id=data['post_id'], body=data['body'])
    return jsonify({'new_id': id}), 201  # Created

如果你必须保持它现在的样子,那么为了不从验证函数返回数据,你必须提出一个HTTPException. 执行此操作的默认功能是flask.abort(code).


推荐阅读