proxy.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. from django.conf import settings
  2. from django.utils.module_loading import import_string
  3. from urllib.parse import urlparse
  4. __all__ = (
  5. 'DefaultProxyRouter',
  6. 'resolve_proxies',
  7. )
  8. class DefaultProxyRouter:
  9. """
  10. Base class for a proxy router.
  11. """
  12. @staticmethod
  13. def _get_protocol_from_url(url):
  14. """
  15. Determine the applicable protocol (e.g. HTTP or HTTPS) from the given URL.
  16. """
  17. return urlparse(url).scheme
  18. def route(self, url=None, protocol=None, context=None):
  19. """
  20. Returns the appropriate proxy given a URL or protocol. Arbitrary context data may also be passed where
  21. available.
  22. Args:
  23. url: The specific request URL for which the proxy will be used (if known)
  24. protocol: The protocol in use (e.g. http or https) (if known)
  25. context: Additional context to aid in proxy selection. May include e.g. the requesting client.
  26. """
  27. if url and protocol is None:
  28. protocol = self._get_protocol_from_url(url)
  29. if protocol and protocol in settings.HTTP_PROXIES:
  30. return {
  31. protocol: settings.HTTP_PROXIES[protocol]
  32. }
  33. return settings.HTTP_PROXIES
  34. def resolve_proxies(url=None, protocol=None, context=None):
  35. """
  36. Return a dictionary of candidate proxies (compatible with the requests module), or None.
  37. Args:
  38. url: The specific request URL for which the proxy will be used (optional)
  39. protocol: The protocol in use (e.g. http or https) (optional)
  40. context: Arbitrary additional context to aid in proxy selection (optional)
  41. """
  42. context = context or {}
  43. for item in settings.PROXY_ROUTERS:
  44. router = import_string(item) if type(item) is str else item
  45. if proxies := router().route(url=url, protocol=protocol, context=context):
  46. return proxies