You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
7.2 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
6 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. # -*- coding: utf-8 -*-
  2. #
  3. # The MIT License (MIT)
  4. #
  5. # Copyright (C) 2017 Marcos Pereira <marcospereira.mpj@gmail.com>
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. # this software and associated documentation files (the "Software"), to deal in
  9. # the Software without restriction, including without limitation the rights to
  10. # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11. # the Software, and to permit persons to whom the Software is furnished to do so,
  12. # subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in all
  15. # copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19. # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21. # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. """Connection manager module."""
  24. try:
  25. from urllib.parse import urljoin
  26. except ImportError: # pragma: no cover
  27. from urlparse import urljoin
  28. import requests
  29. from requests.adapters import HTTPAdapter
  30. from .exceptions import KeycloakConnectionError
  31. class ConnectionManager(object):
  32. """Represents a simple server connection.
  33. :param base_url: (str) The server URL.
  34. :param headers: (dict) The header parameters of the requests to the server.
  35. :param timeout: (int) Timeout to use for requests to the server.
  36. :param verify: (bool) Verify server SSL.
  37. :param proxies: (dict) The proxies servers requests is sent by.
  38. """
  39. def __init__(self, base_url, headers={}, timeout=60, verify=True, proxies=None):
  40. """Init method."""
  41. self.base_url = base_url
  42. self.headers = headers
  43. self.timeout = timeout
  44. self.verify = verify
  45. self._s = requests.Session()
  46. self._s.auth = lambda x: x # don't let requests add auth headers
  47. # retry once to reset connection with Keycloak after tomcat's ConnectionTimeout
  48. # see https://github.com/marcospereirampj/python-keycloak/issues/36
  49. for protocol in ("https://", "http://"):
  50. adapter = HTTPAdapter(max_retries=1)
  51. # adds POST to retry whitelist
  52. allowed_methods = set(adapter.max_retries.allowed_methods)
  53. allowed_methods.add("POST")
  54. adapter.max_retries.allowed_methods = frozenset(allowed_methods)
  55. self._s.mount(protocol, adapter)
  56. if proxies:
  57. self._s.proxies.update(proxies)
  58. def __del__(self):
  59. """Del method."""
  60. self._s.close()
  61. @property
  62. def base_url(self):
  63. """Return base url in use for requests to the server."""
  64. return self._base_url
  65. @base_url.setter
  66. def base_url(self, value):
  67. self._base_url = value
  68. @property
  69. def timeout(self):
  70. """Return timeout in use for request to the server."""
  71. return self._timeout
  72. @timeout.setter
  73. def timeout(self, value):
  74. self._timeout = value
  75. @property
  76. def verify(self):
  77. """Return verify in use for request to the server."""
  78. return self._verify
  79. @verify.setter
  80. def verify(self, value):
  81. self._verify = value
  82. @property
  83. def headers(self):
  84. """Return header request to the server."""
  85. return self._headers
  86. @headers.setter
  87. def headers(self, value):
  88. self._headers = value
  89. def param_headers(self, key):
  90. """Return a specific header parameter.
  91. :param key: (str) Header parameters key.
  92. :returns: If the header parameters exist, return its value.
  93. """
  94. return self.headers.get(key)
  95. def clean_headers(self):
  96. """Clear header parameters."""
  97. self.headers = {}
  98. def exist_param_headers(self, key):
  99. """Check if the parameter exists in the header.
  100. :param key: (str) Header parameters key.
  101. :returns: If the header parameters exist, return True.
  102. """
  103. return self.param_headers(key) is not None
  104. def add_param_headers(self, key, value):
  105. """Add a single parameter inside the header.
  106. :param key: (str) Header parameters key.
  107. :param value: (str) Value to be added.
  108. """
  109. self.headers[key] = value
  110. def del_param_headers(self, key):
  111. """Remove a specific parameter.
  112. :param key: (str) Key of the header parameters.
  113. """
  114. self.headers.pop(key, None)
  115. def raw_get(self, path, **kwargs):
  116. """Submit get request to the path.
  117. :param path: (str) Path for request.
  118. :returns: Response the request.
  119. :raises: HttpError Can't connect to server.
  120. """
  121. try:
  122. return self._s.get(
  123. urljoin(self.base_url, path),
  124. params=kwargs,
  125. headers=self.headers,
  126. timeout=self.timeout,
  127. verify=self.verify,
  128. )
  129. except Exception as e:
  130. raise KeycloakConnectionError("Can't connect to server (%s)" % e)
  131. def raw_post(self, path, data, **kwargs):
  132. """Submit post request to the path.
  133. :param path: (str) Path for request.
  134. :param data: (dict) Payload for request.
  135. :returns: Response the request.
  136. :raises: HttpError Can't connect to server.
  137. """
  138. try:
  139. return self._s.post(
  140. urljoin(self.base_url, path),
  141. params=kwargs,
  142. data=data,
  143. headers=self.headers,
  144. timeout=self.timeout,
  145. verify=self.verify,
  146. )
  147. except Exception as e:
  148. raise KeycloakConnectionError("Can't connect to server (%s)" % e)
  149. def raw_put(self, path, data, **kwargs):
  150. """Submit put request to the path.
  151. :param path: (str) Path for request.
  152. :param data: (dict) Payload for request.
  153. :returns: Response the request.
  154. :raises: HttpError Can't connect to server.
  155. """
  156. try:
  157. return self._s.put(
  158. urljoin(self.base_url, path),
  159. params=kwargs,
  160. data=data,
  161. headers=self.headers,
  162. timeout=self.timeout,
  163. verify=self.verify,
  164. )
  165. except Exception as e:
  166. raise KeycloakConnectionError("Can't connect to server (%s)" % e)
  167. def raw_delete(self, path, data={}, **kwargs):
  168. """Submit delete request to the path.
  169. :param path: (str) Path for request.
  170. :param data: (dict) Payload for request.
  171. :returns: Response the request.
  172. :raises: HttpError Can't connect to server.
  173. """
  174. try:
  175. return self._s.delete(
  176. urljoin(self.base_url, path),
  177. params=kwargs,
  178. data=data,
  179. headers=self.headers,
  180. timeout=self.timeout,
  181. verify=self.verify,
  182. )
  183. except Exception as e:
  184. raise KeycloakConnectionError("Can't connect to server (%s)" % e)