Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion sentry_sdk/integrations/stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ def install_httplib(self):
real_getresponse = self.httplib_connection_cls.getresponse

def putrequest(self, method, url, *args, **kwargs):
rv = real_putrequest(self, method, url, *args, **kwargs)
self._sentrysdk_data_dict = data = {}

host = self.host
port = self.port
default_port = self.default_port
Expand All @@ -30,13 +32,15 @@ def putrequest(self, method, url, *args, **kwargs):
port != default_port and ":%s" % port or "",
url,
)

data["url"] = real_url
data["method"] = method
return real_putrequest(self, method, url, *args, **kwargs)
return rv

def getresponse(self, *args, **kwargs):
rv = real_getresponse(self, *args, **kwargs)
data = getattr(self, "_sentrysdk_data_dict", None) or {}

if "status_code" not in data:
data["status_code"] = rv.status
data["reason"] = rv.reason
Expand Down
48 changes: 48 additions & 0 deletions tests/integrations/stdlib/test_httplib.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import pytest

try:
from urllib.request import urlopen
except ImportError:
from urllib import urlopen

try:
from httplib import HTTPConnection
except ImportError:
from http.client import HTTPConnection

from sentry_sdk import capture_message
from sentry_sdk.integrations.stdlib import StdlibIntegration

Expand Down Expand Up @@ -55,3 +62,44 @@ def before_breadcrumb(crumb, hint):
"reason": "OK",
"extra": "foo",
}


def test_httplib_misuse(sentry_init, capture_events):
"""HTTPConnection.getresponse must be called after every call to
HTTPConnection.request. However, if somebody does not abide by
this contract, we still should handle this gracefully and not
send mixed breadcrumbs.

Test whether our breadcrumbs are coherent when somebody uses HTTPConnection
wrongly.
"""

sentry_init()
events = capture_events()

conn = HTTPConnection("httpbin.org", 80)
conn.request("GET", "/anything/foo")

with pytest.raises(Exception):
# This raises an exception, because we didn't call `getresponse` for
# the previous request yet.
#
# This call should not affect our breadcrumb.
conn.request("POST", "/anything/bar")

response = conn.getresponse()
assert response._method == "GET"

capture_message("Testing!")

event, = events
crumb, = event["breadcrumbs"]

assert crumb["type"] == "http"
assert crumb["category"] == "httplib"
assert crumb["data"] == {
"url": "http://httpbin.org/anything/foo",
"method": "GET",
"status_code": 200,
"reason": "OK",
}