基於 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 授權條款分發的。