utils.py 2.0 KB

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