Skip to content

Commit 55c9f0c

Browse files
committed
Fix httplib invalid scheme detection for HTTPS (aws#121).
* Libraries utilizing urllib3 now properly get matched as https when an https request is made. + botocore and requests utilize urllib3, so any underlying https request now properly identifies as https.
1 parent 9e9063f commit 55c9f0c

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

aws_xray_sdk/ext/httplib/patch.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
PY2 = False
1313
httplib_client_module = 'http.client'
1414
import http.client as httplib
15+
import urllib3.connection
1516
else:
1617
PY2 = True
1718
httplib_client_module = 'httplib'
1819
import httplib
20+
import urllib3.connection
1921

2022

2123
_XRAY_PROP = '_xray_prop'
@@ -92,7 +94,15 @@ def decompose_args(method, url, body, headers, encode_chunked=False):
9294
if subsegment:
9395
inject_trace_header(headers, subsegment)
9496

95-
ssl_cxt = getattr(instance, '_context', None)
97+
if issubclass(instance.__class__, urllib3.connection.HTTPSConnection):
98+
ssl_cxt = getattr(instance, 'ssl_context', None)
99+
elif issubclass(instance.__class__, httplib.HTTPSConnection):
100+
ssl_cxt = getattr(instance, '_context', None)
101+
else:
102+
# In this case, the patcher can't determine which module the connection instance is from.
103+
# We default to it to check ssl_context but may be None so that the default scheme would be
104+
# (and may falsely be) http.
105+
ssl_cxt = getattr(instance, 'ssl_context', None)
96106
scheme = 'https' if ssl_cxt and type(ssl_cxt).__name__ == 'SSLContext' else 'http'
97107
xray_url = '{}://{}{}'.format(scheme, instance.host, url)
98108
xray_data = _XRay_Data(method, instance.host, xray_url)

tests/ext/httplib/test_httplib.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@ def construct_ctx():
3737
unpatch()
3838

3939

40-
def _do_req(url, method='GET'):
40+
def _do_req(url, method='GET', use_https=True):
4141
parts = urlparse(url)
4242
host, _, port = parts.netloc.partition(':')
4343
if port == '':
4444
port = None
45-
conn = httplib.HTTPSConnection(parts.netloc, port)
45+
if use_https:
46+
conn = httplib.HTTPSConnection(parts.netloc, port)
47+
else:
48+
conn = httplib.HTTPConnection(parts.netloc, port)
4649

4750
path = '{}?{}'.format(parts.path, parts.query) if parts.query else parts.path
4851
conn.request(method, path)
@@ -116,3 +119,25 @@ def test_invalid_url():
116119

117120
exception = subsegment.cause['exceptions'][0]
118121
assert exception.type == 'gaierror'
122+
123+
124+
def test_correct_identify_http():
125+
status_code = 200
126+
url = 'http://{}/status/{}?foo=bar&baz=foo'.format(BASE_URL, status_code)
127+
_do_req(url, use_https=False)
128+
subsegment = xray_recorder.current_segment().subsegments[0]
129+
assert subsegment.name == strip_url(url)
130+
131+
http_meta = subsegment.http
132+
assert http_meta['request']['url'].split(":")[0] == 'http'
133+
134+
135+
def test_correct_identify_https():
136+
status_code = 200
137+
url = 'https://{}/status/{}?foo=bar&baz=foo'.format(BASE_URL, status_code)
138+
_do_req(url, use_https=True)
139+
subsegment = xray_recorder.current_segment().subsegments[0]
140+
assert subsegment.name == strip_url(url)
141+
142+
https_meta = subsegment.http
143+
assert https_meta['request']['url'].split(":")[0] == 'https'

0 commit comments

Comments
 (0)