source.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # -*- coding: utf-8 -*-
  2. """
  3. requests_toolbelt.source_adapter
  4. ================================
  5. This file contains an implementation of the SourceAddressAdapter originally
  6. demonstrated on the Requests GitHub page.
  7. """
  8. from requests.adapters import HTTPAdapter
  9. from .._compat import poolmanager, basestring
  10. class SourceAddressAdapter(HTTPAdapter):
  11. """
  12. A Source Address Adapter for Python Requests that enables you to choose the
  13. local address to bind to. This allows you to send your HTTP requests from a
  14. specific interface and IP address.
  15. Two address formats are accepted. The first is a string: this will set the
  16. local IP address to the address given in the string, and will also choose a
  17. semi-random high port for the local port number.
  18. The second is a two-tuple of the form (ip address, port): for example,
  19. ``('10.10.10.10', 8999)``. This will set the local IP address to the first
  20. element, and the local port to the second element. If ``0`` is used as the
  21. port number, a semi-random high port will be selected.
  22. .. warning:: Setting an explicit local port can have negative interactions
  23. with connection-pooling in Requests: in particular, it risks
  24. the possibility of getting "Address in use" errors. The
  25. string-only argument is generally preferred to the tuple-form.
  26. Example usage:
  27. .. code-block:: python
  28. import requests
  29. from requests_toolbelt.adapters.source import SourceAddressAdapter
  30. s = requests.Session()
  31. s.mount('http://', SourceAddressAdapter('10.10.10.10'))
  32. s.mount('https://', SourceAddressAdapter(('10.10.10.10', 8999)))
  33. """
  34. def __init__(self, source_address, **kwargs):
  35. if isinstance(source_address, basestring):
  36. self.source_address = (source_address, 0)
  37. elif isinstance(source_address, tuple):
  38. self.source_address = source_address
  39. else:
  40. raise TypeError(
  41. "source_address must be IP address string or (ip, port) tuple"
  42. )
  43. super(SourceAddressAdapter, self).__init__(**kwargs)
  44. def init_poolmanager(self, connections, maxsize, block=False):
  45. self.poolmanager = poolmanager.PoolManager(
  46. num_pools=connections,
  47. maxsize=maxsize,
  48. block=block,
  49. source_address=self.source_address)
  50. def proxy_manager_for(self, *args, **kwargs):
  51. kwargs['source_address'] = self.source_address
  52. return super(SourceAddressAdapter, self).proxy_manager_for(
  53. *args, **kwargs)