Промежуточное ПО сеансов для приложений Starlette/FastAPI на основе декодирования и кодирования сеансов Flask.
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. Я имею в виду, что мне удалось CRUD данные сеанса на стороне Flask и FastAPI, но я не смог CRUD данные сеанса внутри FastAPI, которые были CRUDированы Flask, поэтому я начал это обсуждение в репозитории FastAPI. Тогда я не смог решить эту проблему, поэтому решил больше не использовать Flask Login и Flask Admin...
Но вы видите, что дискуссия не получила ответов с марта по сентябрь. Меня это беспокоило, поэтому я решил решить эту проблему сам. Я взглянул на исходный код Flask и Starlette (серверное ядро FastAPI). Я обнаружил, что они использовали разные методы для подписи данных сеанса, и Старлетт продолжала повторно подписывать данные сеанса, даже если они не были созданы, обновлены, удалены или даже прочитаны, в этом и была проблема... Мне нужно было специальное SessionMiddleware
, которое использует тот же метод, что и Flask, для подписи данных сеанса, и я его реализовал.
Вот некоторые связанные обсуждения/проблемы/запросы на включение:
SessionMiddleware
добавлен allow_path_regex
от hasansezertasan · Pull Request #2316 · encode/starlette Вот еще один связанный проект: volfpeter/fastapi-flask-auth: облегченные зависимости FastAPI и аутентификатор, который использует файлы cookie сеанса Flask для контроля доступа. Этот проект фактически вдохновил меня на создание starlette-flask
.
Посетите страницу промежуточного программного обеспечения — Starlette, чтобы узнать больше о промежуточном программном обеспечении в Starlette.
Я не эксперт по безопасности. Я просто хотел поделиться своим решением этой проблемы. Если у вас есть какие-либо предложения, пожалуйста, откройте проблему или запрос на включение.
Также есть некоторые проблемы и обсуждения проблем со стандартным
SessionMiddleware
, поставляемым со Starlette. Я считаю, что моя реализация не идеальна, но либоSessionMiddleware
по умолчанию, поставляемое со Starlette.
starlette-flask
распространяется на условиях лицензии MIT.