mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-25 21:36:52 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
43 lines
1.6 KiB
Python
43 lines
1.6 KiB
Python
from typing import AsyncGenerator
|
|
|
|
import httpx
|
|
from fastapi import Request
|
|
from pydantic import BaseModel, Field
|
|
|
|
from openhands.app_server.services.injector import Injector, InjectorState
|
|
|
|
HTTPX_CLIENT_ATTR = 'httpx_client'
|
|
HTTPX_CLIENT_KEEP_OPEN_ATTR = 'httpx_client_keep_open'
|
|
|
|
|
|
class HttpxClientInjector(BaseModel, Injector[httpx.AsyncClient]):
|
|
"""Injector for a httpx client. By keeping a single httpx client alive in the
|
|
context of server requests handshakes are minimized while connection pool leaks
|
|
are prevented."""
|
|
|
|
timeout: int = Field(default=15, description='Default timeout on all http requests')
|
|
|
|
async def inject(
|
|
self, state: InjectorState, request: Request | None = None
|
|
) -> AsyncGenerator[httpx.AsyncClient, None]:
|
|
httpx_client = getattr(state, HTTPX_CLIENT_ATTR, None)
|
|
if httpx_client:
|
|
yield httpx_client
|
|
return
|
|
httpx_client = httpx.AsyncClient(timeout=self.timeout)
|
|
try:
|
|
setattr(state, HTTPX_CLIENT_ATTR, httpx_client)
|
|
yield httpx_client
|
|
finally:
|
|
# If instructed, do not close the httpx client at the end of the request.
|
|
if not getattr(state, HTTPX_CLIENT_KEEP_OPEN_ATTR, False):
|
|
# Clean up the httpx client from request state
|
|
if hasattr(state, HTTPX_CLIENT_ATTR):
|
|
delattr(state, HTTPX_CLIENT_ATTR)
|
|
await httpx_client.aclose()
|
|
|
|
|
|
def set_httpx_client_keep_open(state: InjectorState, keep_open: bool):
|
|
"""Set whether the connection should be kept open after the request terminates."""
|
|
setattr(state, HTTPX_CLIENT_KEEP_OPEN_ATTR, keep_open)
|