Flask限流问题

后端开发 2026-07-07

我在网站上尝试对API请求进行速率限制。然而,当我使用Flask-Limiter时,它却被忽略了。

from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

这是我定义limiter的位置:

limiter = Limiter(
    key_func=get_remote_address,
    default_limits=[],
    storage_uri=os.environ.get("REDIS_URL"),
)

我的用法:

@app.route('/api/gen')
@limiter.limit("1 per day")
def link():
    link=genlink()
    if link:
        return link
    else:
        return jsonify({"error": "No link available"}), 404

我已经正确输入了Redis的 URL,且自部署以来这是我第一次使用Redis,而不是本地环境。这个网页应用托管在Vercel。

解决方案

这是第一个问题:你原本的 Limiter(...) 调用从未绑定应用:

Python

limiter = Limiter(
    key_func=get_remote_address,
    default_limits=[],
    storage_uri=os.environ.get("REDIS_URL"),
)

所有遵循“应用工厂”设计的Flask扩展在创建扩展对象后,只有在将app=app作为参数传给构造函数,或在创建扩展对象后调用limiter.init_app(app) 时,才需要Flask应用对象。若两者都缺失,Limiter将创建一个未绑定的对象;虽然 @limiter.limit(...) 装饰了规则,但它并未接入请求生命周期,因此不会强制执行任何操作,也不会报错。这正是你所经历的行为:没有错误,只是被忽略的调用。官方快速入门指南也能观察到相同的行为:limiter = Limiter( get_remote_address, app=app, storage_uri="redis://localhost:6379", storage_options={"socket_connect_timeout": 30}, strategy="fixed-window" ) 参见: https://flask-limiter.readthedocs.io/en/stable/

第二个问题

当你尝试添加app=app时在本地能工作,但在部署时却报错,这很可能是文件/导入顺序的问题,而不是Redis的问题。这是一个因为在该命名空间中执行app = Flask(_name_) 之前就创建了Limiter(app=app, ...) 的问题,在Vercel上很常见,因为无服务器入口点(通常api/index.py)会从另一个文件导入你的应用,而Limiter(app=app) 在这种情况下所在的模块在你的应用甚至存在之前就被导入了。

解决方案:通过init_app() 实现初始化与绑定的解耦

我在这里附上应该可用的代码

import os
from flask import Flask, jsonify
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)

# Construct without app= to avoid ordering/circular-import issues
limiter = Limiter(
    key_func=get_remote_address,
    default_limits=[],
    storage_uri=os.environ.get("REDIS_URL"),
    storage_options={"socket_connect_timeout": 30},
)
limiter.init_app(app)  # bind AFTER app exists — this is the critical step

def genlink():
    ...

@app.route('/api/gen')
@limiter.limit("1 per day")
def link():
    result = genlink()
    if result:
        return result
    return jsonify({"error": "No link available"}), 404
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章