Middleware de sesión para aplicaciones Starlette/FastAPI basado en la decodificación y codificación de sesiones de Flask.
pip install starlette-flask
Entonces, ¿cuál es el problema? Supongamos que tiene una aplicación Flask y estuvo activa durante mucho tiempo. Quiere migrar a FastAPI pero no quiere que sus usuarios pierdan los datos de su sesión. Y para ser honesto, migrar no es un proceso fácil. Es posible que desee tomarlo con calma y aprovechar las funciones de FastAPI, como montar una aplicación en otra aplicación.
Intentemos montar una aplicación Flask en una aplicación 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 )
El problema aquí es el siguiente: si configura una sesión en la aplicación Flask, no podrá obtenerla desde la aplicación FastAPI y viceversa. Al mismo tiempo, más allá de acceder a los datos de la sesión, estas dos aplicaciones sobrescriben los datos de la sesión de la otra. Esto se debe a que utilizan diferentes métodos para firmar los datos de la sesión.
Dado que utilizan diferentes métodos para firmar los datos de la sesión, no pueden decodificar los datos de la sesión de cada uno. ¿Qué podemos hacer? Podemos usar starlette-flask
para resolver este problema.
Todo lo que necesitas hacer es esto:
- from starlette.middleware.sessions import SessionMiddleware
+ from starlette_flask.middleware.sessions import SessionMiddleware
Estaba migrando de Flask a FastAPI y descubrí que podía usar mis aplicaciones Flask existentes con la aplicación FastAPI (gracias a a2wsgi).
Debo decirles esto: muchas de mis aplicaciones Flask dependen de extensiones de Flask de terceros como Flask Admin, Flask Login y Flask-JWT-Extended.
Entonces busqué cómo acoplar Flask y FastAPI y encontré una manera. Pero hubo un problema... No pude acceder a los datos de la sesión entre las aplicaciones Flask y FastAPI. Quiero decir, pude CRUDar los datos de la sesión en el lado de Flask y FastAPI, pero no pude CRUDar los datos de la sesión dentro de FastAPI que fueron CRUDados por Flask, así que comencé esta discusión en el repositorio de FastAPI. En aquel entonces no pude resolver esto, así que decidí no usar más Flask Login y Flask Admin...
Pero se puede ver que la discusión no obtuvo ninguna respuesta de marzo a septiembre. Me estaba molestando, así que decidí solucionarlo yo mismo. Eché un vistazo al código fuente de Flask y Starlette (núcleo backend de FastAPI). Descubrí que usaban diferentes métodos para firmar los datos de la sesión y Starlette seguía volviendo a firmar los datos de la sesión incluso si no se creaban, actualizaban, eliminaban o incluso leían, ese era el problema... Necesitaba un SessionMiddleware
personalizado que usa el mismo método que Flask para firmar los datos de la sesión y lo implementé.
Aquí hay algunas discusiones/problemas/solicitudes de extracción relacionadas:
allow_path_regex
al SessionMiddleware
por hasansezertasan · Solicitud de extracción n.° 2316 · encode/starlette Aquí hay otro proyecto relacionado: volfpeter/fastapi-flask-auth: autenticador y dependencias FastAPI ligeras que utilizan cookies de sesión de Flask para el control de acceso. Este proyecto realmente me inspiró a construir starlette-flask
.
Consulte la página Middleware - Starlette para obtener más información sobre los middlewares en Starlette.
No soy un experto en seguridad. Solo quería compartir mi solución a este problema. Si tiene alguna sugerencia, abra un problema o una solicitud de extracción.
También hay algunos problemas y discusiones sobre problemas con el
SessionMiddleware
predeterminado que viene con Starlette. Creo que mi implementación no es perfecta, pero tampoco elSessionMiddleware
predeterminado que viene con Starlette.
starlette-flask
se distribuye según los términos de la licencia del MIT.