Custom Backend¶
You can also implement your own backend for your Esmerald application as well. The way of doing it is by subclassing
the SessionBackend
from the package and implement the methods.
SessionBackend¶
Main class of all available backends from Esmerald Sessions.
from esmerald_sessions import SessionBackend
Available backends¶
Esmerald Sessions brings some built-in backends to be used within any Esmerald application.
AioMemCacheSessionBackend¶
from esmerald_sessions import AioMemCacheSessionBackend
AioRedisSessionBackend¶
from esmerald_sessions import AioRedisSessionBackend
MemCacheSessionBackend¶
from esmerald_sessions import MemCacheSessionBackend
RedisSessionBackend¶
from esmerald_sessions import RedisSessionBackend
Implement a custom backend¶
As mentioned before, all the custom backends must inherit from SessionBackend
and implement the methods.
from typing import TYPE_CHECKING, Any, Optional
from esmerald_sessions import SessionBackend
if TYPE_CHECKING:
from pydantic.typing import DictAny
class MyCustomBackend(SessionBackend):
async def get(self, key: str, **kwargs: "DictAny") -> Optional["DictAny"]:
# Add logic here
...
async def set(
self, key: str, value: "DictAny", expire: Optional[int], **kwargs: "DictAny"
) -> Optional[str]:
# Add logic here
...
async def delete(self, key: str, **kwargs: "DictAny") -> Any:
# Add logic here
...
Example¶
backend.py
from typing import TYPE_CHECKING, Any, Optional
from esmerald_sessions import SessionBackend
if TYPE_CHECKING:
from pydantic.typing import DictAny
class Client:
# Your new client and logic here
...
class MyCustomBackend(SessionBackend):
client: Optional[Client]
def __init__(self, client: Client, **kwargs: "DictAny") -> None:
super().__init__(**kwargs)
self.client = client
async def get(self, key: str, **kwargs: "DictAny") -> Optional["DictAny"]:
value = await self.client.get(key, **kwargs)
return value if value else None
async def set(
self, key: str, value: "DictAny", expire: Optional[int], **kwargs: "DictAny"
) -> Optional[str]:
return await self.client.set(key, value, expire=expire, **kwargs)
async def delete(self, key: str, **kwargs: "DictAny") -> Any:
return await self.client.delete(key, **kwargs)
Now we can add the new client to the application.
backend.py
from enums import BackendType
from esmerald import Esmerald, Gateway, get, post
from esmerald.requests import Request
from esmerald.responses import JSONResponse
from esmerald.utils.crypto import get_random_secret_key
from starlette.middleware import Middleware
from esmerald_sessions import SessionConfig, SessionMiddleware
from .backend import MyCustomBackend
@get()
async def view_session(request: Request) -> JSONResponse:
return JSONResponse({"session": request.session})
@post()
async def setup_session(request: Request) -> JSONResponse:
request.session.update({"data": "session.data"})
return JSONResponse({"session": request.session})
@post()
async def clear_session(request: Request) -> JSONResponse:
request.session.clear()
return JSONResponse({"session": request.session})
custom_client = MyCustomBackend(...)
session_config = SessionConfig(
secret_key=get_random_secret_key(),
cookie_name="cookie",
backend_type=BackendType.redis,
custom_session_backend=custom_client,
)
app = Esmerald(
routes=[
Gateway("/view-session", handler=view_session),
Gateway("/setup-session", handler=setup_session),
Gateway("/clear-session", handler=clear_session),
],
middleware=[Middleware(SessionMiddleware, config=session_config)],
)
As you can see, the difference between the built-in backends and the custom is the fact that the custom should always be passed into the custom_session_backend property.