utils.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. from __future__ import annotations
  2. import asyncio
  3. import urllib.parse
  4. from uvicorn._types import WWWScope
  5. class ClientDisconnected(OSError): ...
  6. def get_remote_addr(transport: asyncio.Transport) -> tuple[str, int] | None:
  7. socket_info = transport.get_extra_info("socket")
  8. if socket_info is not None:
  9. try:
  10. info = socket_info.getpeername()
  11. return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None
  12. except OSError: # pragma: no cover
  13. # This case appears to inconsistently occur with uvloop
  14. # bound to a unix domain socket.
  15. return None
  16. info = transport.get_extra_info("peername")
  17. if info is not None and isinstance(info, (list, tuple)) and len(info) == 2:
  18. return (str(info[0]), int(info[1]))
  19. return None
  20. def get_local_addr(transport: asyncio.Transport) -> tuple[str, int] | None:
  21. socket_info = transport.get_extra_info("socket")
  22. if socket_info is not None:
  23. info = socket_info.getsockname()
  24. return (str(info[0]), int(info[1])) if isinstance(info, tuple) else None
  25. info = transport.get_extra_info("sockname")
  26. if info is not None and isinstance(info, (list, tuple)) and len(info) == 2:
  27. return (str(info[0]), int(info[1]))
  28. return None
  29. def is_ssl(transport: asyncio.Transport) -> bool:
  30. return bool(transport.get_extra_info("sslcontext"))
  31. def get_client_addr(scope: WWWScope) -> str:
  32. client = scope.get("client")
  33. if not client:
  34. return ""
  35. return "%s:%d" % client
  36. def get_path_with_query_string(scope: WWWScope) -> str:
  37. path_with_query_string = urllib.parse.quote(scope["path"])
  38. if scope["query_string"]:
  39. path_with_query_string = "{}?{}".format(path_with_query_string, scope["query_string"].decode("ascii"))
  40. return path_with_query_string