import logging from aiohttp import web from apollo_utils.service.exceptions import APIError, BadGateway from asyncio import CancelledError from sentry_sdk import capture_exception from typing import Callable from server import config from server.cache.modes import set_cache_mode from server.client.utils import pass_headers from server.utils.auth import check_authorization logger = logging.getLogger("app") @web.middleware async def error_middleware(request: web.Request, handler: Callable) -> web.Response: """Callback for handling exceptions.""" try: return await handler(request) except (CancelledError, APIError) as ex: if isinstance(ex, CancelledError): ex = BadGateway(detail="Request was cancelled.") elif ex.status_code not in config.SENTRY_IGNORE_STATUS_CODES: capture_exception(ex) return web.json_response(data=ex.to_dict(), status=ex.status_code) @web.middleware async def logging_middleware(request: web.Request, handler: Callable) -> web.Response: """Callback for logging requests.""" response = await handler(request) logger.info(f"[{response.status}] {request.method} {request.rel_url}") return response @web.middleware async def auth_middleware(request: web.Request, handler: Callable) -> web.Response: """Authenticate a user. Raises: Unauthorized: If authorization token is invalid or missing. """ check_authorization(request) return await handler(request) @web.middleware async def headers_middleware(request: web.Request, handler: Callable) -> web.Response: """Callback to store request headers and pass them to inner services if needed.""" set_cache_mode(request) pass_headers(request) return await handler(request)