mirror of
https://github.com/rommapp/romm.git
synced 2026-02-18 23:42:07 +01:00
This change replaces the `httpx` client with `aiohttp` for the RetroAchievements API service. The main reason for this change is that `httpx` has an unavoidable log line with `INFO` level, which includes the request full URL, containing the user's API key. `httpx` has had an [open discussion](https://github.com/encode/httpx/discussions/2765) regarding this security issue for almost two years. The change to `aiohttp` is painless, and would allow us to migrate more of the codebase to it in the future, to avoid leaking sensitive information in logs.
51 lines
1.6 KiB
Python
51 lines
1.6 KiB
Python
from collections.abc import AsyncGenerator, Awaitable, Callable
|
|
from contextlib import asynccontextmanager
|
|
from contextvars import ContextVar, Token
|
|
from typing import TypeVar
|
|
|
|
import aiohttp
|
|
import httpx
|
|
from fastapi import Request, Response
|
|
|
|
_T = TypeVar("_T")
|
|
|
|
ctx_aiohttp_session: ContextVar[aiohttp.ClientSession] = ContextVar("aiohttp_session")
|
|
ctx_httpx_client: ContextVar[httpx.AsyncClient] = ContextVar("httpx_client")
|
|
|
|
|
|
@asynccontextmanager
|
|
async def set_context_var(
|
|
var: ContextVar[_T], value: _T
|
|
) -> AsyncGenerator[Token[_T], None]:
|
|
"""Temporarily set a context variables."""
|
|
token = var.set(value)
|
|
yield token
|
|
var.reset(token)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def initialize_context() -> AsyncGenerator[None, None]:
|
|
"""Initialize context variables."""
|
|
async with (
|
|
aiohttp.ClientSession() as aiohttp_session,
|
|
httpx.AsyncClient() as httpx_client,
|
|
set_context_var(ctx_aiohttp_session, aiohttp_session),
|
|
set_context_var(ctx_httpx_client, httpx_client),
|
|
):
|
|
yield
|
|
|
|
|
|
async def set_context_middleware(
|
|
request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
|
) -> Response:
|
|
"""Initialize context variables in FastAPI request-response cycle.
|
|
|
|
This middleware is needed because the context initialized during the lifespan
|
|
process is not available in the request-response cycle.
|
|
"""
|
|
async with (
|
|
set_context_var(ctx_aiohttp_session, request.app.state.aiohttp_session),
|
|
set_context_var(ctx_httpx_client, request.app.state.httpx_client),
|
|
):
|
|
return await call_next(request)
|