Middleware de session pour les applications Starlette/FastAPI basées sur le décodage et l'encodage de session Flask.
pip install starlette-flask
Alors quel est le problème ? Disons que vous avez une application Flask et qu'elle est en ligne depuis longtemps. Vous souhaitez migrer vers FastAPI mais vous ne souhaitez pas que vos utilisateurs perdent leurs données de session. Et pour être honnête, migrer n’est pas un processus facile. Vous souhaiterez peut-être y aller lentement et bénéficier des fonctionnalités de FastAPI, telles que le montage d'une application sur une autre application.
Essayons de monter une application Flask sur une application 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 )
Le problème ici est le suivant : si vous définissez une session dans l'application Flask, vous ne pouvez pas l'obtenir à partir de l'application FastAPI, et vice versa. Dans le même temps, au-delà de l'accès aux données de session, ces deux applications écrasent mutuellement les données de session. C'est parce qu'ils utilisent des méthodes différentes pour signer les données de session.
Puisqu'ils utilisent des méthodes différentes pour signer les données de session, ils ne peuvent pas décoder les données de session de chacun. Que pouvons-nous faire ? Nous pouvons utiliser starlette-flask
pour résoudre ce problème.
Tout ce que vous avez à faire est ceci :
- from starlette.middleware.sessions import SessionMiddleware
+ from starlette_flask.middleware.sessions import SessionMiddleware
Je migrais de Flask vers FastAPI et j'ai découvert que je pouvais utiliser mes applications Flask existantes avec l'application FastAPI (grâce à a2wsgi).
Je dois vous dire ceci : beaucoup de mes applications Flask dépendent d'extensions Flask tierces telles que Flask Admin, Flask Login et Flask-JWT-Extended.
J'ai donc cherché comment coupler Flask et FastAPI et j'ai trouvé un moyen. Mais il y a eu un problème... Je n'ai pas pu accéder aux données de session entre les applications Flask et FastAPI. Je veux dire, j'ai pu CRUD les données de session côté Flask et FastAPI, mais je n'ai pas pu CRUD les données de session à l'intérieur de FastAPI qui ont été CRUDées par Flask, j'ai donc commencé cette discussion dans le référentiel FastAPI. À l'époque, je n'étais pas en mesure de résoudre ce problème, j'ai donc décidé de ne plus utiliser Flask Login et Flask Admin...
Mais vous voyez que la discussion n'a pas trouvé de réponse de mars à septembre. Cela me dérangeait, alors j'ai décidé de le résoudre moi-même. J'ai jeté un œil au code source de Flask et Starlette (noyau backend de FastAPI). J'ai découvert qu'ils utilisaient différentes méthodes pour signer les données de session et que Starlette continuait à signer à nouveau les données de session même si elles n'étaient pas créées, mises à jour, supprimées ou même lues, c'était le problème... J'avais besoin d'un SessionMiddleware
personnalisé qui utilise la même méthode que Flask pour signer les données de session et je l'ai implémentée.
Voici quelques discussions/problèmes/demandes d'extraction connexes :
allow_path_regex
au SessionMiddleware
par hasansezertasan · Pull Request #2316 · encode/starlette Voici un autre projet connexe : volfpeter/fastapi-flask-auth : dépendances FastAPI légères et authentificateur qui utilise les cookies de session Flask pour le contrôle d'accès. Ce projet m'a en fait inspiré pour construire starlette-flask
.
Consultez la page Middleware - Starlette pour en savoir plus sur les middlewares dans Starlette.
Je ne suis pas un expert en sécurité. Je voulais juste partager ma solution à ce problème. Si vous avez des suggestions, veuillez ouvrir un problème ou une pull request.
Il y a également quelques problèmes et discussions sur les problèmes liés au
SessionMiddleware
par défaut fourni avec Starlette. Je pense que mon implémentation n'est pas parfaite, mais leSessionMiddleware
par défaut fourni avec Starlette non plus.
starlette-flask
est distribué selon les termes de la licence MIT.