test_http.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import io
  2. import platform
  3. from unittest.mock import patch
  4. import brotli
  5. import pytest
  6. import responses
  7. from django.core.exceptions import SuspiciousOperation
  8. from urllib3.util.connection import HAS_IPV6
  9. from sentry import http
  10. from sentry.testutils.helpers import override_blacklist
  11. @responses.activate
  12. @patch("socket.getaddrinfo")
  13. def test_simple(mock_getaddrinfo):
  14. mock_getaddrinfo.return_value = [(2, 1, 6, "", ("81.0.0.1", 0))]
  15. responses.add(responses.GET, "http://example.com", body="foo bar")
  16. resp = http.safe_urlopen("http://example.com")
  17. data = http.safe_urlread(resp)
  18. assert data.decode("utf-8") == "foo bar"
  19. request = responses.calls[0].request
  20. assert "User-Agent" in request.headers
  21. assert "gzip" in request.headers.get("Accept-Encoding", "")
  22. @override_blacklist("127.0.0.1", "::1", "10.0.0.0/8")
  23. # XXX(dcramer): we can't use responses here as it hooks Session.send
  24. # @responses.activate
  25. def test_ip_blacklist_ipv4():
  26. with pytest.raises(SuspiciousOperation):
  27. http.safe_urlopen("http://127.0.0.1")
  28. with pytest.raises(SuspiciousOperation):
  29. http.safe_urlopen("http://10.0.0.10")
  30. with pytest.raises(SuspiciousOperation):
  31. # '2130706433' is dword for '127.0.0.1'
  32. http.safe_urlopen("http://2130706433")
  33. @pytest.mark.skipif(not HAS_IPV6, reason="needs ipv6")
  34. @override_blacklist("::1")
  35. def test_ip_blacklist_ipv6():
  36. with pytest.raises(SuspiciousOperation):
  37. http.safe_urlopen("http://[::1]")
  38. @pytest.mark.skipif(HAS_IPV6, reason="stub for non-ipv6 systems")
  39. @override_blacklist("::1")
  40. @patch("socket.getaddrinfo")
  41. def test_ip_blacklist_ipv6_fallback(mock_getaddrinfo):
  42. mock_getaddrinfo.return_value = [(10, 1, 6, "", ("::1", 0, 0, 0))]
  43. with pytest.raises(SuspiciousOperation):
  44. http.safe_urlopen("http://[::1]")
  45. @pytest.mark.skipif(
  46. platform.system() == "Darwin", reason="macOS is always broken, see comment in sentry/http.py"
  47. )
  48. @override_blacklist("127.0.0.1")
  49. def test_garbage_ip():
  50. with pytest.raises(SuspiciousOperation):
  51. # '0177.0000.0000.0001' is an octal for '127.0.0.1'
  52. http.safe_urlopen("http://0177.0000.0000.0001")
  53. @responses.activate
  54. def test_fetch_file():
  55. responses.add(
  56. responses.GET, "http://example.com", body="foo bar", content_type="application/json"
  57. )
  58. temp = io.BytesIO()
  59. result = http.fetch_file(url="http://example.com", domain_lock_enabled=False, outfile=temp)
  60. assert result.body is None
  61. assert temp.getvalue() == b"foo bar"
  62. @responses.activate
  63. def test_fetch_file_brotli():
  64. body = brotli.compress(b"foo bar")
  65. responses.add(
  66. responses.GET,
  67. "http://example.com",
  68. body=body,
  69. content_type="application/json",
  70. adding_headers={"Content-Encoding": "br"},
  71. )
  72. temp = io.BytesIO()
  73. result = http.fetch_file(url="http://example.com", domain_lock_enabled=False, outfile=temp)
  74. assert result.body is None
  75. assert temp.getvalue() == b"foo bar"