test_http.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Nicole Thomas <nicole@saltstack.com>
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import socket
  7. from contextlib import closing
  8. import salt.utils.http as http
  9. from tests.support.helpers import MirrorPostHandler, Webserver, slowTest
  10. from tests.support.unit import TestCase
  11. class HTTPTestCase(TestCase):
  12. """
  13. Unit TestCase for the salt.utils.http module.
  14. """
  15. @classmethod
  16. def setUpClass(cls):
  17. cls.post_webserver = Webserver(handler=MirrorPostHandler)
  18. cls.post_webserver.start()
  19. cls.post_web_root = cls.post_webserver.web_root
  20. @classmethod
  21. def tearDownClass(cls):
  22. cls.post_webserver.stop()
  23. del cls.post_webserver
  24. # sanitize_url tests
  25. def test_sanitize_url_hide_fields_none(self):
  26. """
  27. Tests sanitizing a url when the hide_fields kwarg is None.
  28. """
  29. mock_url = "https://api.testing.com/?&foo=bar&test=testing"
  30. ret = http.sanitize_url(mock_url, hide_fields=None)
  31. self.assertEqual(ret, mock_url)
  32. def test_sanitize_url_no_elements(self):
  33. """
  34. Tests sanitizing a url when no elements should be sanitized.
  35. """
  36. mock_url = "https://api.testing.com/?&foo=bar&test=testing"
  37. ret = http.sanitize_url(mock_url, [""])
  38. self.assertEqual(ret, mock_url)
  39. def test_sanitize_url_single_element(self):
  40. """
  41. Tests sanitizing a url with only a single element to be sanitized.
  42. """
  43. mock_url = (
  44. "https://api.testing.com/?&keep_it_secret=abcdefghijklmn"
  45. "&api_action=module.function"
  46. )
  47. mock_ret = (
  48. "https://api.testing.com/?&keep_it_secret=XXXXXXXXXX&"
  49. "api_action=module.function"
  50. )
  51. ret = http.sanitize_url(mock_url, ["keep_it_secret"])
  52. self.assertEqual(ret, mock_ret)
  53. def test_sanitize_url_multiple_elements(self):
  54. """
  55. Tests sanitizing a url with multiple elements to be sanitized.
  56. """
  57. mock_url = (
  58. "https://api.testing.com/?rootPass=badpassword%21"
  59. "&skipChecks=True&api_key=abcdefghijklmn"
  60. "&NodeID=12345&api_action=module.function"
  61. )
  62. mock_ret = (
  63. "https://api.testing.com/?rootPass=XXXXXXXXXX"
  64. "&skipChecks=True&api_key=XXXXXXXXXX"
  65. "&NodeID=12345&api_action=module.function"
  66. )
  67. ret = http.sanitize_url(mock_url, ["api_key", "rootPass"])
  68. self.assertEqual(ret, mock_ret)
  69. # _sanitize_components tests
  70. def test_sanitize_components_no_elements(self):
  71. """
  72. Tests when zero elements need to be sanitized.
  73. """
  74. mock_component_list = ["foo=bar", "bar=baz", "hello=world"]
  75. mock_ret = "foo=bar&bar=baz&hello=world&"
  76. ret = http._sanitize_url_components(mock_component_list, "api_key")
  77. self.assertEqual(ret, mock_ret)
  78. def test_sanitize_components_one_element(self):
  79. """
  80. Tests a single component to be sanitized.
  81. """
  82. mock_component_list = ["foo=bar", "api_key=abcdefghijklmnop"]
  83. mock_ret = "foo=bar&api_key=XXXXXXXXXX&"
  84. ret = http._sanitize_url_components(mock_component_list, "api_key")
  85. self.assertEqual(ret, mock_ret)
  86. def test_sanitize_components_multiple_elements(self):
  87. """
  88. Tests two componenets to be sanitized.
  89. """
  90. mock_component_list = ["foo=bar", "foo=baz", "api_key=testing"]
  91. mock_ret = "foo=XXXXXXXXXX&foo=XXXXXXXXXX&api_key=testing&"
  92. ret = http._sanitize_url_components(mock_component_list, "foo")
  93. self.assertEqual(ret, mock_ret)
  94. @slowTest
  95. def test_query_null_response(self):
  96. """
  97. This tests that we get a null response when raise_error=False and the
  98. host/port cannot be reached.
  99. """
  100. host = "127.0.0.1"
  101. # Find unused port
  102. with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
  103. sock.bind((host, 0))
  104. port = sock.getsockname()[1]
  105. url = "http://{host}:{port}/".format(host=host, port=port)
  106. result = http.query(url, raise_error=False)
  107. assert result == {"body": None}, result
  108. def test_query_error_handling(self):
  109. ret = http.query("http://127.0.0.1:0")
  110. self.assertTrue(isinstance(ret, dict))
  111. self.assertTrue(isinstance(ret.get("error", None), str))
  112. ret = http.query("http://myfoobardomainthatnotexist")
  113. self.assertTrue(isinstance(ret, dict))
  114. self.assertTrue(isinstance(ret.get("error", None), str))
  115. class HTTPPostTestCase(TestCase):
  116. """
  117. Unit TestCase for the salt.utils.http module when
  118. using POST method
  119. """
  120. @classmethod
  121. def setUpClass(cls):
  122. cls.post_webserver = Webserver(handler=MirrorPostHandler)
  123. cls.post_webserver.start()
  124. cls.post_web_root = cls.post_webserver.web_root
  125. @classmethod
  126. def tearDownClass(cls):
  127. cls.post_webserver.stop()
  128. del cls.post_webserver
  129. def test_requests_multipart_formdata_post(self):
  130. """
  131. Test handling of a multipart/form-data POST using the requests backend
  132. """
  133. match_this = '{0}\r\nContent-Disposition: form-data; name="fieldname_here"\r\n\r\nmydatahere\r\n{0}--\r\n'
  134. ret = http.query(
  135. self.post_web_root,
  136. method="POST",
  137. data="mydatahere",
  138. formdata=True,
  139. formdata_fieldname="fieldname_here",
  140. backend="requests",
  141. )
  142. body = ret.get("body", "")
  143. boundary = body[: body.find("\r")]
  144. self.assertEqual(body, match_this.format(boundary))
  145. class HTTPGetTestCase(TestCase):
  146. """
  147. Unit TestCase for the salt.utils.http module when
  148. using Get method
  149. """
  150. @classmethod
  151. def setUpClass(cls):
  152. cls.get_webserver = Webserver()
  153. cls.get_webserver.start()
  154. @classmethod
  155. def tearDownClass(cls):
  156. cls.get_webserver.stop()
  157. del cls.get_webserver
  158. def test_backends_decode_body_false(self):
  159. """
  160. test all backends when using
  161. decode_body=False that it returns
  162. bytes and does not try to decode
  163. """
  164. for backend in ["tornado", "requests", "urllib2"]:
  165. ret = http.query(
  166. self.get_webserver.url("custom.tar.gz"),
  167. backend=backend,
  168. decode_body=False,
  169. )
  170. body = ret.get("body", "")
  171. assert isinstance(body, bytes)
  172. def test_backends_decode_body_true(self):
  173. """
  174. test all backends when using
  175. decode_body=True that it returns
  176. string and decodes it.
  177. """
  178. for backend in ["tornado", "requests", "urllib2"]:
  179. ret = http.query(self.get_webserver.url("core.sls"), backend=backend,)
  180. body = ret.get("body", "")
  181. assert isinstance(body, str)