使用Flask-Limiter动态加载限制字符串的问题

时间:2019-04-11 08:56:21

标签: api flask python-3.5 throttling

我正在跟踪docs,以获取动态加载的限制字符串。基本上,我正在尝试实施公司特定的RATE LIMIT。 以下是公司模型:

# company model
    class Company(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(100), unique=True)
        limit = db.Column(db.String(50), default=DEFAULT_LIMIT)

        def __init__(self, name, limit):
            self.name = name
            self.limit = limit

这是我的limiter.py:

DEFAULT_LIMIT = "100/day, 10/minute"

app = Flask(__name__)

# defining limiter
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=[DEFAULT_LIMIT] # this is default limit set for app
)

def get_company_limit():
    try:
        company = Company.query.get(request.view_args['id'])
        return app.config.get("CUSTOM_LIMIT", company.limit)
    except:
        abort(403) # if company not found then raise forbidden

# an end point
@app.route("/company/<id>", methods=["GET"])
@limiter.limit(get_company_limit)
def get_company(id):
    return "success"

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

让我们假设这些是公司:

[
    {
        "name": "company1"
        "limit": "100/day, 5/minute",
    },
    {
       "name": "company2"
        "limit": "100/day, 10/minute",
    },
    {
        "name": "company3"
        "limit": "50/day, 5/minute",
    },
    {
       "name": "company4"
        "limit": "100/day, 2/minute",
    }
]

问题: 动态获取的限制可以与公司1、2和4一起正常使用。但是如您所见,company1和company3有一些匹配的限制(5 /分钟),无论调用api结束的顺序如何,这些公司都可以共享限制点。到达终点时,company1和company3共享极限计数器5。

例如,如果使用company1 id调用了3次端点,则使用company3 id调用时,在2次成功响应后,限制器将提高429。同时为company1提高429。

无法理解这种行为以及我想了解的东西?

1 个答案:

答案 0 :(得分:0)

问题在于:

# defining limiter
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=[DEFAULT_LIMIT] # this is default limit set for app
)

在这里,get_remote_address基本上是key_func与每个新请求发生冲突时使用。对于每个请求,它可能返回客户端接口的相同远程地址。需要用户定义的key_func来调节请求。

def get_comany_id():
    return (Company.query.get(request.view_args['id']), 0)

# defining limiter
limiter = Limiter(
    app,
    key_func=get_comany_id,
    default_limits=[DEFAULT_LIMIT] # this is default limit set for app
)

它奏效了。