guess.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. # -*- coding: utf-8 -*-
  2. """The module containing the code for GuessAuth."""
  3. from requests import auth
  4. from requests import cookies
  5. from . import _digest_auth_compat as auth_compat, http_proxy_digest
  6. class GuessAuth(auth.AuthBase):
  7. """Guesses the auth type by the WWW-Authentication header."""
  8. def __init__(self, username, password):
  9. self.username = username
  10. self.password = password
  11. self.auth = None
  12. self.pos = None
  13. def _handle_basic_auth_401(self, r, kwargs):
  14. if self.pos is not None:
  15. r.request.body.seek(self.pos)
  16. # Consume content and release the original connection
  17. # to allow our new request to reuse the same one.
  18. r.content
  19. r.raw.release_conn()
  20. prep = r.request.copy()
  21. if not hasattr(prep, '_cookies'):
  22. prep._cookies = cookies.RequestsCookieJar()
  23. cookies.extract_cookies_to_jar(prep._cookies, r.request, r.raw)
  24. prep.prepare_cookies(prep._cookies)
  25. self.auth = auth.HTTPBasicAuth(self.username, self.password)
  26. prep = self.auth(prep)
  27. _r = r.connection.send(prep, **kwargs)
  28. _r.history.append(r)
  29. _r.request = prep
  30. return _r
  31. def _handle_digest_auth_401(self, r, kwargs):
  32. self.auth = auth_compat.HTTPDigestAuth(self.username, self.password)
  33. try:
  34. self.auth.init_per_thread_state()
  35. except AttributeError:
  36. # If we're not on requests 2.8.0+ this method does not exist and
  37. # is not relevant.
  38. pass
  39. # Check that the attr exists because much older versions of requests
  40. # set this attribute lazily. For example:
  41. # https://github.com/kennethreitz/requests/blob/33735480f77891754304e7f13e3cdf83aaaa76aa/requests/auth.py#L59
  42. if (hasattr(self.auth, 'num_401_calls') and
  43. self.auth.num_401_calls is None):
  44. self.auth.num_401_calls = 1
  45. # Digest auth would resend the request by itself. We can take a
  46. # shortcut here.
  47. return self.auth.handle_401(r, **kwargs)
  48. def handle_401(self, r, **kwargs):
  49. """Resends a request with auth headers, if needed."""
  50. www_authenticate = r.headers.get('www-authenticate', '').lower()
  51. if 'basic' in www_authenticate:
  52. return self._handle_basic_auth_401(r, kwargs)
  53. if 'digest' in www_authenticate:
  54. return self._handle_digest_auth_401(r, kwargs)
  55. def __call__(self, request):
  56. if self.auth is not None:
  57. return self.auth(request)
  58. try:
  59. self.pos = request.body.tell()
  60. except AttributeError:
  61. pass
  62. request.register_hook('response', self.handle_401)
  63. return request
  64. class GuessProxyAuth(GuessAuth):
  65. """
  66. Guesses the auth type by WWW-Authentication and Proxy-Authentication
  67. headers
  68. """
  69. def __init__(self, username=None, password=None,
  70. proxy_username=None, proxy_password=None):
  71. super(GuessProxyAuth, self).__init__(username, password)
  72. self.proxy_username = proxy_username
  73. self.proxy_password = proxy_password
  74. self.proxy_auth = None
  75. def _handle_basic_auth_407(self, r, kwargs):
  76. if self.pos is not None:
  77. r.request.body.seek(self.pos)
  78. r.content
  79. r.raw.release_conn()
  80. prep = r.request.copy()
  81. if not hasattr(prep, '_cookies'):
  82. prep._cookies = cookies.RequestsCookieJar()
  83. cookies.extract_cookies_to_jar(prep._cookies, r.request, r.raw)
  84. prep.prepare_cookies(prep._cookies)
  85. self.proxy_auth = auth.HTTPProxyAuth(self.proxy_username,
  86. self.proxy_password)
  87. prep = self.proxy_auth(prep)
  88. _r = r.connection.send(prep, **kwargs)
  89. _r.history.append(r)
  90. _r.request = prep
  91. return _r
  92. def _handle_digest_auth_407(self, r, kwargs):
  93. self.proxy_auth = http_proxy_digest.HTTPProxyDigestAuth(
  94. username=self.proxy_username,
  95. password=self.proxy_password)
  96. try:
  97. self.auth.init_per_thread_state()
  98. except AttributeError:
  99. pass
  100. return self.proxy_auth.handle_407(r, **kwargs)
  101. def handle_407(self, r, **kwargs):
  102. proxy_authenticate = r.headers.get('Proxy-Authenticate', '').lower()
  103. if 'basic' in proxy_authenticate:
  104. return self._handle_basic_auth_407(r, kwargs)
  105. if 'digest' in proxy_authenticate:
  106. return self._handle_digest_auth_407(r, kwargs)
  107. def __call__(self, request):
  108. if self.proxy_auth is not None:
  109. request = self.proxy_auth(request)
  110. try:
  111. self.pos = request.body.tell()
  112. except AttributeError:
  113. pass
  114. request.register_hook('response', self.handle_407)
  115. return super(GuessProxyAuth, self).__call__(request)