基于 Flask 会话解码和编码的 Starlette/FastAPI 应用程序的会话中间件。
pip install starlette-flask
那么问题出在哪里呢?假设您有一个 Flask 应用程序,并且它已经运行了很长时间。您想要迁移到 FastAPI,但不希望用户丢失其会话数据。老实说,迁移并不是一个容易的过程。您可能希望慢慢来并享受 FastAPI 功能的好处,例如将一个应用程序安装到另一个应用程序。
让我们尝试将 Flask 应用程序挂载到 FastAPI 应用程序。
from fastapi import FastAPI , Request , Response
from flask import Flask , jsonify , session , request
from starlette . middleware . sessions import SessionMiddleware
from a2wsgi import WSGIMiddleware
secret_key = "super-secret"
flask_app = Flask ( __name__ )
flask_app . config [ "SECRET_KEY" ] = secret_key
@ flask_app . get ( "/" )
def flask_index ():
return jsonify ({ "message" : "Hello World from Flask Application" })
@ flask_app . get ( "/set-session" )
def flask_set_session ():
session [ "application" ] = "flask"
session . modified = True
return jsonify ({ "message" : "Session set" })
@ flask_app . get ( "/get-session" )
def flask_get_session ():
return jsonify ({ "message" : session . get ( "application" , None )})
@ flask_app . get ( "/delete-session" )
def flask_delete_session ():
session . pop ( "application" )
session . modified = True
return jsonify ({ "message" : "Session deleted" })
@ flask_app . before_request
def before_request ():
print ( session . items ())
@ flask_app . after_request
def after_request ( response ):
print ( session . items ())
return response
fastapi_application = FastAPI ()
fastapi_application . add_middleware (
SessionMiddleware ,
secret_key = secret_key ,
)
@ fastapi_application . middleware ( "http" )
async def starlette_add_process_time_header ( request : Request , call_next ):
response = await call_next ( request )
response . headers [ "X-Process-Time" ] = "100"
print ( response . headers )
return response
@ fastapi_application . get ( "/" )
async def starlette_index ( req : Request ):
return { "message" : "Hello World from FastAPI Application" }
@ fastapi_application . get ( "/set-session" )
async def starlette_set_session ( req : Request ):
req . session . update ({ "application" : "fastapi" })
return { "message" : "Session set" }
@ fastapi_application . get ( "/get-session" )
async def starlette_get_session ( req : Request ):
return { "message" : req . session . get ( "application" , None )}
@ fastapi_application . get ( "/delete-session" )
async def starlette_delete_session ( req : Request ):
req . session . pop ( "application" )
return { "message" : "Session deleted" }
app = FastAPI ()
app . mount ( "/flask-application" , WSGIMiddleware ( flask_app ))
app . mount ( "/fastapi-application" , fastapi_application )
这里的问题是这样的:如果你在 Flask 应用程序中设置会话,你无法从 FastAPI 应用程序中获取它,反之亦然。同时,除了访问会话数据之外,这两个应用程序还会覆盖彼此的会话数据。这是因为他们使用不同的方法来签署会话数据。
由于它们使用不同的方法对会话数据进行签名,因此它们无法解码彼此的会话数据。我们能做什么?我们可以使用starlette-flask
来解决这个问题。
您需要做的就是:
- from starlette.middleware.sessions import SessionMiddleware
+ from starlette_flask.middleware.sessions import SessionMiddleware
我从 Flask 迁移到 FastAPI,发现我可以将现有的 Flask 应用程序与 FastAPI(感谢 a2wsgi)应用程序一起使用。
我必须告诉你:我的许多 Flask 应用程序都依赖于第三方 Flask 扩展,例如 Flask Admin、Flask Login 和 Flask-JWT-Extended
所以我搜索了如何耦合Flask和FastAPI并找到了一种方法。但有一个问题......我无法访问 Flask 和 FastAPI 应用程序之间的会话数据。我的意思是我能够在 Flask 端和 FastAPI 端对会话数据进行 CRUD,但是我无法对由 Flask 进行 CRUD 处理的 FastAPI 中的会话数据进行 CRUD,所以我在 FastAPI 存储库中开始了这个讨论。当时我无法解决这个问题,所以我决定不再使用 Flask Login 和 Flask Admin ......
但你可以看到,从3月到9月的讨论并没有得到任何答案。这件事困扰着我,所以我决定自己解决。我看了一下Flask和Starlette(FastAPI的后端核心)的源代码。我发现他们使用不同的方法来签署会话数据,而 Starlette 不断地重新签署会话数据,即使它没有创建、更新、删除,甚至没有读取,这就是问题所在......我需要一个自定义的SessionMiddleware
使用与 Flask 相同的方法来签署会话数据,我确实实现了它。
以下是一些相关的讨论/问题/拉取请求:
allow_path_regex
添加到SessionMiddleware
· Pull Request #2316 · 编码/starlette这是另一个相关项目:volfpeter/fastapi-flask-auth:轻量级 FastAPI 依赖项和身份验证器,使用 Flask 会话 cookie 进行访问控制。这个项目实际上激发了我构建starlette-flask
。
查看 Middleware - Starlette 页面,了解有关 Starlette 中中间件的更多信息。
我不是安全专家。我只是想分享我对这个问题的解决方案。如果您有任何建议,请提出问题或拉取请求。
还有一些关于 Starlette 附带的默认
SessionMiddleware
问题的问题和讨论。我相信我的实现并不完美,但 Starlette 附带的默认SessionMiddleware
也不是完美的。
starlette-flask
是根据 MIT 许可证条款分发的。