def test_send(waiting_httpserver): waiting_httpserver.serve_content( code=202, content="", headers={"Location": "http://example.com/foo"}) transport = Transport(waiting_httpserver.url) try: url = transport.send(compat.b("x")) assert url == "http://example.com/foo" finally: transport.close()
def test_ssl_verify_fails(waiting_httpsserver): waiting_httpsserver.serve_content(code=202, content="", headers={"Location": "http://example.com/foo"}) transport = Transport(waiting_httpsserver.url) try: with pytest.raises(TransportException) as exc_info: url = transport.send(compat.b("x")) assert "CERTIFICATE_VERIFY_FAILED" in str(exc_info) finally: transport.close()
def test_ssl_verify_disable(waiting_httpsserver): waiting_httpsserver.serve_content( code=202, content="", headers={"Location": "https://example.com/foo"}) transport = Transport(waiting_httpsserver.url, verify_server_cert=False) try: url = transport.send(compat.b("x")) assert url == "https://example.com/foo" finally: transport.close()
def test_generic_error(): url, status, message, body = ( 'http://localhost:9999', 418, "I'm a teapot", 'Nothing' ) transport = Transport(urlparse.urlparse(url)) responses.add('POST', '/', status=status, body=Exception('Oopsie')) with pytest.raises(TransportException) as exc_info: transport.send('x', {}) assert 'Oopsie' in str(exc_info.value)
def test_timeout(): transport = Transport(urlparse.urlparse("http://localhost")) responses.add("POST", "/", status=202, body=MaxRetryError(None, None, reason=TimeoutError())) with pytest.raises(TransportException) as exc_info: transport.send("x", {}, timeout=5) assert "timeout" in str(exc_info.value)
def test_fetch_server_info(waiting_httpserver, elasticapm_client): waiting_httpserver.serve_content( code=200, content=b'{"version": "8.0.0-alpha1"}', ) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) transport.fetch_server_info() assert elasticapm_client.server_version == (8, 0, 0, "alpha1")
def test_ssl_cert_pinning(waiting_httpsserver): waiting_httpsserver.serve_content( code=202, content="", headers={"Location": "https://example.com/foo"}) transport = Transport(waiting_httpsserver.url, server_cert=DEFAULT_CERTIFICATE, verify_server_cert=True) try: url = transport.send(compat.b("x")) assert url == "https://example.com/foo" finally: transport.close()
def test_get_config_handle_exception(mock_urlopen, caplog, elasticapm_client): transport = Transport("http://example.com/" + constants.EVENTS_API_PATH, client=elasticapm_client) mock_urlopen.side_effect = urllib3.exceptions.RequestError( transport.http, "http://example.com/", "boom") with caplog.at_level("DEBUG", "elasticapm.transport.http"): version, data, max_age = transport.get_config("1", {}) assert version == "1" assert max_age == 300 record = caplog.records[-1] assert "HTTP error" in record.msg
def test_https_proxy_environment_variable_is_preferred(): with mock.patch.dict("os.environ", { "https_proxy": "https://example.com", "HTTP_PROXY": "http://example.com" }): transport = Transport("http://localhost:9999") try: assert isinstance(transport.http, urllib3.poolmanager.ProxyManager) assert transport.http.proxy.scheme == "https" finally: transport.close()
def test_ssl_cert_pinning(waiting_httpsserver): waiting_httpsserver.serve_content(code=202, content="", headers={"Location": "https://example.com/foo"}) cur_dir = os.path.dirname(os.path.realpath(__file__)) transport = Transport( waiting_httpsserver.url, server_cert=os.path.join(cur_dir, "..", "ca/server.pem"), verify_server_cert=True ) try: url = transport.send(compat.b("x")) assert url == "https://example.com/foo" finally: transport.close()
def test_no_proxy_host(): with mock.patch.dict("os.environ", { "HTTPS_PROXY": "https://example.com", "NO_PROXY": "localhost" }): transport = Transport("http://localhost:9999") try: assert not isinstance(transport.http, urllib3.poolmanager.ProxyManager) finally: transport.close()
def test_get_config_empty_response(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content(code=200, content=b"", headers={"Cache-Control": "max-age=5"}) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) with caplog.at_level("DEBUG", "elasticapm.transport.http"): version, data, max_age = transport.get_config("1", {}) assert version == "1" assert data is None assert max_age == 5 record = caplog.records[-1] assert record.message == "APM Server answered with empty body and status code 200"
def test_get_config_cache_headers_304(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content(code=304, content=b"", headers={"Cache-Control": "max-age=5"}) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) with caplog.at_level("DEBUG", "elasticapm.transport.http"): version, data, max_age = transport.get_config("1", {}) assert waiting_httpserver.requests[0].headers["If-None-Match"] == "1" assert version == "1" assert data is None assert max_age == 5 record = caplog.records[-1] assert "Configuration unchanged" in record.msg
def test_get_config_bad_cache_control_header(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content( code=200, content=b'{"x": "y"}', headers={"Cache-Control": "max-age=fifty", "Etag": "2"} ) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) with caplog.at_level("DEBUG", "elasticapm.transport.http"): version, data, max_age = transport.get_config("1", {}) assert version == "2" assert data == {"x": "y"} assert max_age == 300 record = caplog.records[-1] assert record.message == "Could not parse Cache-Control header: max-age=fifty"
def test_ssl_verify_disable_http(waiting_httpserver): """ Make sure that ``assert_hostname`` isn't passed in for http requests, even with verify_server_cert=False """ waiting_httpserver.serve_content( code=202, content="", headers={"Location": "http://example.com/foo"}) transport = Transport(waiting_httpserver.url, verify_server_cert=False) try: url = transport.send(compat.b("x")) assert url == "http://example.com/foo" finally: transport.close()
def test_get_config(waiting_httpserver, elasticapm_client): waiting_httpserver.serve_content(code=200, content=b'{"x": "y"}', headers={ "Cache-Control": "max-age=5", "Etag": "2" }) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) version, data, max_age = transport.get_config("1", {}) assert version == "2" assert data == {"x": "y"} assert max_age == 5
def test_header_encodings(elasticapm_client): """ Tests that headers are encoded as bytestrings. If they aren't, urllib assumes it needs to encode the data as well, which is already a zlib encoded bytestring, and explodes. """ headers = {compat.text_type("X"): compat.text_type("V")} elasticapm_client.server_version = (8, 0 ) # avoid making server_info request transport = Transport("http://localhost:9999", headers=headers, client=elasticapm_client) transport.start_thread() try: with mock.patch("elasticapm.transport.http.urllib3.PoolManager.urlopen" ) as mock_urlopen: mock_urlopen.return_value = mock.Mock(status=202) transport.send("") _, args, kwargs = mock_urlopen.mock_calls[0] if compat.PY2: assert isinstance(args[1], compat.binary_type) for k, v in kwargs["headers"].items(): assert isinstance(k, compat.binary_type) assert isinstance(v, compat.binary_type) finally: transport.close()
def test_ssl_cert_pinning_fails(waiting_httpsserver, elasticapm_client): if compat.PY3: waiting_httpsserver.serve_content( code=202, content="", headers={"Location": "https://example.com/foo"}) url = waiting_httpsserver.url else: # if we use the local test server here, execution blocks somewhere deep in OpenSSL on Python 2.7, presumably # due to a threading issue that has been fixed in later versions. To avoid that, we have to commit a minor # cardinal sin here and do an outside request to https://example.com (which will also fail the fingerprint # assertion). # # May the Testing Goat have mercy on our souls. url = "https://example.com" transport = Transport( url, server_cert=os.path.join(os.path.dirname(__file__), "wrong_cert.pem"), verify_server_cert=True, client=elasticapm_client, ) transport.start_thread() try: with pytest.raises(TransportException) as exc_info: transport.send(compat.b("x")) finally: transport.close() assert "Fingerprints did not match" in exc_info.value.args[0]
def test_fetch_server_info_flat_string(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content( code=200, content=b'"8.0.0-alpha1"', ) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) with caplog.at_level("WARNING"): transport.fetch_server_info() assert elasticapm_client.server_version is None assert_any_record_contains(caplog.records, "No version key found in server response")
def test_fetch_server_info_no_json(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content( code=200, content=b'"version": "8.0.0-alpha1"', ) url = waiting_httpserver.url transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) with caplog.at_level("WARNING"): transport.fetch_server_info() assert elasticapm_client.server_version is None assert_any_record_contains( caplog.records, "JSON decoding error while fetching server information")
def test_no_proxy_star(): with mock.patch.dict("os.environ", { "HTTPS_PROXY": "https://example.com", "NO_PROXY": "*" }): transport = Transport("http://localhost:9999", client=None) assert not isinstance(transport.http, urllib3.poolmanager.ProxyManager)
def test_ssl_cert_pinning_http(waiting_httpserver): """ Won't fail, as with the other cert pinning test, since certs aren't relevant for http, only https. """ waiting_httpserver.serve_content( code=202, content="", headers={"Location": "http://example.com/foo"}) transport = Transport( waiting_httpserver.url, server_cert=os.path.join(os.path.dirname(__file__), "wrong_cert.pem"), verify_server_cert=True, ) try: url = transport.send(compat.b("x")) assert url == "http://example.com/foo" finally: transport.close()
def test_get_config(waiting_httpserver, elasticapm_client): waiting_httpserver.serve_content( code=200, content=b'{"x": "y"}', headers={"Cache-Control": "max-age=5", "Etag": "2"} ) url = waiting_httpserver.url transport = Transport( url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client, headers={"Content-Type": "application/x-ndjson", "Content-Encoding": "gzip"}, ) version, data, max_age = transport.get_config("1", {}) assert version == "2" assert data == {"x": "y"} assert max_age == 5 assert "Content-Encoding" not in waiting_httpserver.requests[0].headers assert waiting_httpserver.requests[0].headers["Content-Type"] == "application/json"
def test_timeout(mock_urlopen, elasticapm_client): transport = Transport("http://localhost", timeout=5, client=elasticapm_client) transport.start_thread() mock_urlopen.side_effect = MaxRetryError(None, None, reason=TimeoutError()) try: with pytest.raises(TransportException) as exc_info: transport.send("x") assert "timeout" in str(exc_info.value) finally: transport.close()
def test_http_error(waiting_httpserver, elasticapm_client): waiting_httpserver.serve_content(code=418, content="I'm a teapot") transport = Transport(waiting_httpserver.url, client=elasticapm_client) transport.start_thread() try: with pytest.raises(TransportException) as exc_info: transport.send("x") for val in (418, "I'm a teapot"): assert str(val) in str(exc_info.value) finally: transport.close()
def test_generic_error(mock_urlopen, elasticapm_client): url, status, message, body = ("http://localhost:9999", 418, "I'm a teapot", "Nothing") transport = Transport(url, client=elasticapm_client) transport.start_thread() mock_urlopen.side_effect = Exception("Oopsie") try: with pytest.raises(TransportException) as exc_info: transport.send("x") assert "Oopsie" in str(exc_info.value) finally: transport.close()
def test_header_encodings(): """ Tests that headers are encoded as bytestrings. If they aren't, urllib assumes it needs to encode the data as well, which is already a zlib encoded bytestring, and explodes. """ headers = {compat.text_type("X"): compat.text_type("V")} transport = Transport(urlparse.urlparse("http://localhost:9999")) with mock.patch("elasticapm.transport.http.urllib3.PoolManager.urlopen" ) as mock_urlopen: mock_urlopen.return_value = mock.Mock(status=202) transport.send("", headers) _, args, kwargs = mock_urlopen.mock_calls[0] if compat.PY2: assert isinstance(args[1], compat.binary_type) for k, v in kwargs["headers"].items(): assert isinstance(k, compat.binary_type) assert isinstance(v, compat.binary_type)
def test_ssl_verify_fails(waiting_httpsserver, elasticapm_client): waiting_httpsserver.serve_content(code=202, content="", headers={"Location": "http://example.com/foo"}) transport = Transport(waiting_httpsserver.url, client=elasticapm_client) transport.start_thread() try: with pytest.raises(TransportException) as exc_info: url = transport.send(compat.b("x")) assert "certificate verify failed" in str(exc_info) finally: transport.close()
def test_generic_error(): url, status, message, body = ("http://localhost:9999", 418, "I'm a teapot", "Nothing") transport = Transport(url) responses.add("POST", "/", status=status, body=Exception("Oopsie")) try: with pytest.raises(TransportException) as exc_info: transport.send("x") assert "Oopsie" in str(exc_info.value) finally: transport.close()
def test_config_url(): transport = Transport("http://example.com/" + constants.EVENTS_API_PATH) try: assert transport._config_url == "http://example.com/" + constants.AGENT_CONFIG_PATH finally: transport.close()