From c2a6f0571b4bd8cbd4f4ef6e26ca5233fb4708cf Mon Sep 17 00:00:00 2001 From: jobala Date: Mon, 2 Mar 2020 19:03:00 +0300 Subject: [PATCH 1/5] Enhance requests with middlwares --- src/constants.py | 4 +++ src/core/http_client_factory.py | 22 ++++++++++++++++ tests/test.py | 0 tests/test_http_client.py | 44 +++++++++++++++++++++++++++++++ tests/test_http_client_factory.py | 29 ++++++++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 src/constants.py create mode 100644 src/core/http_client_factory.py delete mode 100644 tests/test.py create mode 100644 tests/test_http_client.py create mode 100644 tests/test_http_client_factory.py diff --git a/src/constants.py b/src/constants.py new file mode 100644 index 00000000..62ce1a9a --- /dev/null +++ b/src/constants.py @@ -0,0 +1,4 @@ +REQUEST_TIMEOUT = 100 +CONNECTION_TIMEOUT = 30 +BASE_URL = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0' +SDK_VERSION = 'graph-python-0.0.1' diff --git a/src/core/http_client_factory.py b/src/core/http_client_factory.py new file mode 100644 index 00000000..d9d231f9 --- /dev/null +++ b/src/core/http_client_factory.py @@ -0,0 +1,22 @@ +from requests import Session + +from requests_middleware import MiddlewareHTTPAdapter + +from src.constants import BASE_URL, SDK_VERSION + + +class HTTPClientFactory: + @classmethod + def with_graph_middlewares(cls, middlewares): + return _HTTPClient(middlewares=middlewares) + + +class _HTTPClient(Session): + """ + TODO: Add support for attaching multiple adapters + """ + def __init__(self, **kwargs): + super(_HTTPClient, self).__init__() + self.headers.update({'sdkVersion': SDK_VERSION}) + self._base_url = BASE_URL + self.adapter = MiddlewareHTTPAdapter(kwargs.get('middlewares')) diff --git a/tests/test.py b/tests/test.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/test_http_client.py b/tests/test_http_client.py new file mode 100644 index 00000000..edad7f68 --- /dev/null +++ b/tests/test_http_client.py @@ -0,0 +1,44 @@ +from unittest import TestCase + +from requests import Session + +from src.core.http_client_factory import _HTTPClient +from src.constants import BASE_URL, SDK_VERSION + + +class HTTPClientTest(TestCase): + def setUp(self) -> None: + self.requests = _HTTPClient() + + def tearDown(self) -> None: + self.requests = None + + def test_creates_instance_of_session(self): + self.assertIsInstance(self.requests, Session) + + def test_has_graph_url_as_base_url(self): + self.assertEqual(self.requests._base_url, BASE_URL) + + def test_has_sdk_version_header(self): + self.assertEqual(self.requests.headers.get('sdkVersion'), SDK_VERSION) + + def test_configure_http_proxy(self): + """ + TODO: Support HTTP proxies + :return: + """ + pass + + def test_gzip_compresses_payloads(self): + """ + TODO: Compress payloads + :return: + """ + pass + + def test_uses_tls_1_point_2(self): + """ + Use TLS 1.2 + :return: + """ + pass diff --git a/tests/test_http_client_factory.py b/tests/test_http_client_factory.py new file mode 100644 index 00000000..d992b5ea --- /dev/null +++ b/tests/test_http_client_factory.py @@ -0,0 +1,29 @@ +import unittest + +from requests_middleware import BaseMiddleware +from requests.adapters import HTTPAdapter + +from src.core.http_client_factory import HTTPClientFactory + + +class HTTPClientFactoryTest(unittest.TestCase): + def test_initialized_with_middlewares(self): + middlewares = [ + _MockMiddleware() + ] + + requests = HTTPClientFactory.with_graph_middlewares(middlewares) + _, mocked_middleware = requests.adapters.popitem() + + self.assertIsInstance(mocked_middleware, HTTPAdapter) + + def test_created_with_authentication_provider(self): + """ + TODO: Implement create with authentication provider + :return: + """ + pass + + +class _MockMiddleware(BaseMiddleware): + pass From c351c635c48497e2da7a0417b9f223a54a21d7e7 Mon Sep 17 00:00:00 2001 From: jobala Date: Mon, 2 Mar 2020 19:41:25 +0300 Subject: [PATCH 2/5] Remove todo comment --- src/core/http_client_factory.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/http_client_factory.py b/src/core/http_client_factory.py index d9d231f9..7d7dab29 100644 --- a/src/core/http_client_factory.py +++ b/src/core/http_client_factory.py @@ -12,9 +12,6 @@ def with_graph_middlewares(cls, middlewares): class _HTTPClient(Session): - """ - TODO: Add support for attaching multiple adapters - """ def __init__(self, **kwargs): super(_HTTPClient, self).__init__() self.headers.update({'sdkVersion': SDK_VERSION}) From 188dbe5fd69e82c54dffa3ecaccb90e54eb5ab83 Mon Sep 17 00:00:00 2001 From: jobala Date: Mon, 2 Mar 2020 20:37:19 +0300 Subject: [PATCH 3/5] Update HttpClientFactory test --- tests/test_http_client_factory.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_http_client_factory.py b/tests/test_http_client_factory.py index d992b5ea..0572406b 100644 --- a/tests/test_http_client_factory.py +++ b/tests/test_http_client_factory.py @@ -1,7 +1,6 @@ import unittest -from requests_middleware import BaseMiddleware -from requests.adapters import HTTPAdapter +from requests_middleware import BaseMiddleware, MiddlewareHTTPAdapter from src.core.http_client_factory import HTTPClientFactory @@ -13,9 +12,9 @@ def test_initialized_with_middlewares(self): ] requests = HTTPClientFactory.with_graph_middlewares(middlewares) - _, mocked_middleware = requests.adapters.popitem() + mocked_middleware = requests.get_adapter('https://') - self.assertIsInstance(mocked_middleware, HTTPAdapter) + self.assertIsInstance(mocked_middleware, MiddlewareHTTPAdapter) def test_created_with_authentication_provider(self): """ From 7d0493a8b8d8b7af43e108d98982840ee5d6bfc2 Mon Sep 17 00:00:00 2001 From: jobala Date: Mon, 2 Mar 2020 20:38:45 +0300 Subject: [PATCH 4/5] Override Session's PUT, POST, PATCH, UPDATE & DELETE --- src/constants.py | 1 + src/core/http_client_factory.py | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/constants.py b/src/constants.py index 62ce1a9a..84b2ec66 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,4 +1,5 @@ REQUEST_TIMEOUT = 100 CONNECTION_TIMEOUT = 30 +# TODO: Change this to graph.microsoft.com/v1.0 BASE_URL = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0' SDK_VERSION = 'graph-python-0.0.1' diff --git a/src/core/http_client_factory.py b/src/core/http_client_factory.py index 7d7dab29..e3ce4adb 100644 --- a/src/core/http_client_factory.py +++ b/src/core/http_client_factory.py @@ -16,4 +16,26 @@ def __init__(self, **kwargs): super(_HTTPClient, self).__init__() self.headers.update({'sdkVersion': SDK_VERSION}) self._base_url = BASE_URL - self.adapter = MiddlewareHTTPAdapter(kwargs.get('middlewares')) + + adapter = MiddlewareHTTPAdapter(kwargs.get('middlewares')) + self.mount('https://', adapter) + + def get(self, url, **kwargs): + graph_url = self._base_url+url + super(_HTTPClient, self).get(graph_url, **kwargs) + + def post(self, url, data=None, json=None, **kwargs): + graph_url = self._base_url+url + super(_HTTPClient, self).post(graph_url, data=None, json=None, **kwargs) + + def put(self, url, data=None, **kwargs): + graph_url = self._base_url+url + super(_HTTPClient, self).put(graph_url, data=None, **kwargs) + + def patch(self, url, data=None, **kwargs): + graph_url = self._base_url+url + super(_HTTPClient, self).patch(graph_url, data=None, **kwargs) + + def delete(self, url, **kwargs): + graph_url = self._base_url+url + super(_HTTPClient, self).delete(graph_url, **kwargs) From 57f1fde47b9eb2470dc6f0dd800e945fe7cbd007 Mon Sep 17 00:00:00 2001 From: jobala Date: Tue, 3 Mar 2020 12:59:26 +0300 Subject: [PATCH 5/5] Add support for non graph urls --- src/constants.py | 3 +-- src/core/http_client_factory.py | 24 +++++++++++-------- tests/test_http_client.py | 40 +++++++++++++++---------------- tests/test_http_client_factory.py | 10 +++----- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/constants.py b/src/constants.py index 84b2ec66..a3b78c48 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,5 +1,4 @@ REQUEST_TIMEOUT = 100 CONNECTION_TIMEOUT = 30 -# TODO: Change this to graph.microsoft.com/v1.0 -BASE_URL = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https://graph.microsoft.com/v1.0' +BASE_URL = 'https://graph.microsoft.com/v1.0' SDK_VERSION = 'graph-python-0.0.1' diff --git a/src/core/http_client_factory.py b/src/core/http_client_factory.py index e3ce4adb..552b267b 100644 --- a/src/core/http_client_factory.py +++ b/src/core/http_client_factory.py @@ -21,21 +21,25 @@ def __init__(self, **kwargs): self.mount('https://', adapter) def get(self, url, **kwargs): - graph_url = self._base_url+url - super(_HTTPClient, self).get(graph_url, **kwargs) + request_url = self._get_url(url) + super(_HTTPClient, self).get(request_url, **kwargs) def post(self, url, data=None, json=None, **kwargs): - graph_url = self._base_url+url - super(_HTTPClient, self).post(graph_url, data=None, json=None, **kwargs) + request_url = self._get_url(url) + super(_HTTPClient, self).post(request_url, data=None, json=None, **kwargs) def put(self, url, data=None, **kwargs): - graph_url = self._base_url+url - super(_HTTPClient, self).put(graph_url, data=None, **kwargs) + request_url = self._get_url(url) + super(_HTTPClient, self).put(request_url, data=None, **kwargs) def patch(self, url, data=None, **kwargs): - graph_url = self._base_url+url - super(_HTTPClient, self).patch(graph_url, data=None, **kwargs) + request_url = self._get_url(url) + super(_HTTPClient, self).patch(request_url, data=None, **kwargs) def delete(self, url, **kwargs): - graph_url = self._base_url+url - super(_HTTPClient, self).delete(graph_url, **kwargs) + request_url = self._get_url(url) + super(_HTTPClient, self).delete(request_url, **kwargs) + + def _get_url(self, url): + return self._base_url+url if (url[0] == '/') else url + diff --git a/tests/test_http_client.py b/tests/test_http_client.py index edad7f68..e806653e 100644 --- a/tests/test_http_client.py +++ b/tests/test_http_client.py @@ -1,6 +1,7 @@ from unittest import TestCase from requests import Session +import responses from src.core.http_client_factory import _HTTPClient from src.constants import BASE_URL, SDK_VERSION @@ -22,23 +23,22 @@ def test_has_graph_url_as_base_url(self): def test_has_sdk_version_header(self): self.assertEqual(self.requests.headers.get('sdkVersion'), SDK_VERSION) - def test_configure_http_proxy(self): - """ - TODO: Support HTTP proxies - :return: - """ - pass - - def test_gzip_compresses_payloads(self): - """ - TODO: Compress payloads - :return: - """ - pass - - def test_uses_tls_1_point_2(self): - """ - Use TLS 1.2 - :return: - """ - pass + @responses.activate + def test_builds_graph_urls(self): + graph_url = BASE_URL+'/me' + responses.add(responses.GET, graph_url, status=200) + + self.requests.get('/me') + request_url = responses.calls[0].request.url + + self.assertEqual(graph_url, request_url) + + @responses.activate + def test_does_not_build_graph_urls_for_full_urls(self): + other_url = 'https://microsoft.com/' + responses.add(responses.GET, other_url, status=200) + + self.requests.get(other_url) + request_url = responses.calls[0].request.url + + self.assertEqual(other_url, request_url) diff --git a/tests/test_http_client_factory.py b/tests/test_http_client_factory.py index 0572406b..95488256 100644 --- a/tests/test_http_client_factory.py +++ b/tests/test_http_client_factory.py @@ -1,14 +1,14 @@ -import unittest +from unittest import TestCase from requests_middleware import BaseMiddleware, MiddlewareHTTPAdapter from src.core.http_client_factory import HTTPClientFactory -class HTTPClientFactoryTest(unittest.TestCase): +class HTTPClientFactoryTest(TestCase): def test_initialized_with_middlewares(self): middlewares = [ - _MockMiddleware() + BaseMiddleware() ] requests = HTTPClientFactory.with_graph_middlewares(middlewares) @@ -22,7 +22,3 @@ def test_created_with_authentication_provider(self): :return: """ pass - - -class _MockMiddleware(BaseMiddleware): - pass