Files
drf-rack/net/xeaf/rack/managers/request_manager.py

121 lines
3.4 KiB
Python

# DRF Rack
# Библиотека классов расширений для Django REST Framework
#
# Автор: Николай В. Анохин <n.anokhin@xeaf.net>
# Все права защищены. Лицензия: MIT
"""
Описание класса RequestManager
"""
import uuid
from typing import Any
from uuid import UUID
from django.core.exceptions import ImproperlyConfigured
from rest_framework.request import Request
from net.xeaf.rack.models import AccountModel
from net.xeaf.rack.models import SessionModel
from net.xeaf.rack.utils.exceptions import BadRequestException
from net.xeaf.rack.utils.exceptions import UnauthorizedException
class RequestManager:
"""
Реализует методы работы с запросами
"""
REQUEST_ID_META = "X-Request-ID"
""" Идентификатор запроса """
@classmethod
def get_request_id(cls, request: Request) -> UUID:
"""
Возвращает идентификатор запроса
:param request: Объект запроса
:return: Идентификатор запроса
"""
request_id = request.headers.get(cls.REQUEST_ID_META, None)
if request_id is None:
return uuid.uuid4()
try:
return UUID(str(request_id))
except ValueError:
raise BadRequestException()
@classmethod
def get_request_method(cls, request: Request) -> str:
"""
Возвращает имя метода HTTP протокола запроса
:param request: Объект запроса
:return: Имя метода HTTP протокола запроса
"""
method = request.method
if not method:
raise ImproperlyConfigured()
return method.upper()
@classmethod
def get_request_session[T: SessionModel](cls, request: Request) -> T | None:
"""
Возвращает сессию, связанную с текущим запросом
:param request: Объект запроса
:return: Сессия, связанная с текущим запросом
"""
# noinspection PyTypeChecker
session: SessionModel | None = request.auth
return session
@classmethod
def get_request_account[T: AccountModel](cls, request: Request) -> T:
"""
Возвращает аккаунт, связанный с текущим запросом
:param request: Объект запроса
:return: Аккаунт, связанный с текущим запросом
"""
session = cls.get_request_session(request)
if session is not None:
# noinspection PyTypeChecker
account: T | None = session.account
if account is not None:
return account
raise UnauthorizedException()
@classmethod
def get_request_context(cls, request: Request) -> dict[str, Any]:
"""
Возвращает контекст запроса
:param request: Объект запроса
:return: Объект контекста запроса
"""
try:
account = cls.get_request_account(request)
except UnauthorizedException:
account = None
return {
"id": cls.get_request_id(request),
"account": account,
"request": request
}