FastAPI中间件更新Cookie后通知需两次刷新的问题排查与解决
问题原因分析与解决方案
原因解析
当前中间件的执行逻辑是先处理请求(包括渲染HTML模板),再查询通知数并设置Cookie,这就导致了两次刷新的问题:
- 第一次刷新时,模板渲染依赖的是浏览器发送请求时携带的旧Cookie,此时新的通知Cookie还没被设置
- Cookie是在响应阶段才写入浏览器的,只有第二次刷新时,浏览器才会把新Cookie带过来,模板才能读到最新的通知数
解决方案1:直接将通知数注入请求上下文(推荐)
跳过Cookie的往返依赖,在请求处理前就查询最新通知数,存入请求上下文,让模板直接读取这个实时值。
修改middleware.py:
async def get_user_notifications(request: Request, call_next): # 先查询最新通知数,再处理请求 if await is_authenticated(request): user = await get_current_user(request) if user['is_notified']: notifications = await MessagesService.get_count(int(user['user_id'])) request.state.notification_count = notifications['total'] if notifications else 0 else: request.state.notification_count = 0 else: request.state.notification_count = 0 response = await call_next(request) return response
修改HTML模板:
{% if request.state.notification_count > 0 %} <small class="notification-badge">{{request.state.notification_count}}</small> {% else %} <small class="notification-badge-empty">0</small> {% endif %}
这样请求处理阶段就能拿到最新的通知数据,一次刷新即可显示结果。
解决方案2:保留Cookie同时同步模板数据(适用于需Cookie做其他逻辑的场景)
如果业务上需要保留user_notifications Cookie,可以在设置Cookie的同时,把实时通知数注入请求上下文,让模板直接使用上下文里的最新值,无需依赖请求携带的Cookie。
修改middleware.py:
async def get_user_notifications(request: Request, call_next): notification_count = 0 if await is_authenticated(request): user = await get_current_user(request) if user['is_notified']: notifications = await MessagesService.get_count(int(user['user_id'])) notification_count = notifications['total'] if notifications else 0 # 存入请求上下文供模板实时使用 request.state.notification_count = notification_count response = await call_next(request) # 同步设置/清除Cookie if notification_count > 0: response.set_cookie( key="user_notifications", value=str(notification_count), httponly=True, ) else: response.delete_cookie("user_notifications") return response
修改HTML模板:
{% if request.state.notification_count > 0 %} <small class="notification-badge">{{request.state.notification_count}}</small> {% else %} <small class="notification-badge-empty">0</small> {% endif %}
内容的提问来源于stack exchange,提问作者Jekson
相关产品推荐
相关产品推荐

