From bf7af707b9430d2f6b8b76649f2368bf7058010a Mon Sep 17 00:00:00 2001 From: Elena Kolevska Date: Wed, 18 Oct 2023 17:55:32 +0100 Subject: [PATCH 1/4] Fixes bug of constructor argument being used as http endpoint Signed-off-by: Elena Kolevska --- dapr/clients/__init__.py | 3 +-- dapr/clients/http/client.py | 10 +++------- dapr/clients/http/dapr_invocation_http_client.py | 5 ++--- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/dapr/clients/__init__.py b/dapr/clients/__init__.py index da5f373b..4586b040 100644 --- a/dapr/clients/__init__.py +++ b/dapr/clients/__init__.py @@ -79,8 +79,7 @@ def __init__( if http_timeout_seconds is None: http_timeout_seconds = settings.DAPR_HTTP_TIMEOUT_SECONDS self.invocation_client = DaprInvocationHttpClient(headers_callback=headers_callback, - timeout=http_timeout_seconds, - address=address) + timeout=http_timeout_seconds) elif invocation_protocol == 'GRPC': pass else: diff --git a/dapr/clients/http/client.py b/dapr/clients/http/client.py index da66ea30..d0f178b2 100644 --- a/dapr/clients/http/client.py +++ b/dapr/clients/http/client.py @@ -37,8 +37,7 @@ class DaprHttpClient: def __init__(self, message_serializer: 'Serializer', timeout: Optional[int] = 60, - headers_callback: Optional[Callable[[], Dict[str, str]]] = None, - address: Optional[str] = None): + headers_callback: Optional[Callable[[], Dict[str, str]]] = None): """Invokes Dapr over HTTP. Args: @@ -49,15 +48,12 @@ def __init__(self, self._timeout = aiohttp.ClientTimeout(total=timeout) self._serializer = message_serializer self._headers_callback = headers_callback - self._address = address def get_api_url(self) -> str: - if self._address: - return '{}/{}'.format(self._address, settings.DAPR_API_VERSION) if settings.DAPR_HTTP_ENDPOINT: return '{}/{}'.format(settings.DAPR_HTTP_ENDPOINT, settings.DAPR_API_VERSION) - else: - return 'http://{}:{}/{}'.format(settings.DAPR_RUNTIME_HOST, + + return 'http://{}:{}/{}'.format(settings.DAPR_RUNTIME_HOST, settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION) async def send_bytes( diff --git a/dapr/clients/http/dapr_invocation_http_client.py b/dapr/clients/http/dapr_invocation_http_client.py index 0010fad5..af965639 100644 --- a/dapr/clients/http/dapr_invocation_http_client.py +++ b/dapr/clients/http/dapr_invocation_http_client.py @@ -34,15 +34,14 @@ class DaprInvocationHttpClient: def __init__( self, timeout: int = 60, - headers_callback: Optional[Callable[[], Dict[str, str]]] = None, - address: Optional[str] = None): + headers_callback: Optional[Callable[[], Dict[str, str]]] = None): """Invokes Dapr's API for method invocation over HTTP. Args: timeout (int, optional): Timeout in seconds, defaults to 60. headers_callback (lambda: Dict[str, str]], optional): Generates header for each request. """ - self._client = DaprHttpClient(DefaultJSONSerializer(), timeout, headers_callback, address) + self._client = DaprHttpClient(DefaultJSONSerializer(), timeout, headers_callback) async def invoke_method_async( self, From 4b85bef00f4cb70302a5f58d697499bdf97ea50a Mon Sep 17 00:00:00 2001 From: Elena Kolevska Date: Wed, 18 Oct 2023 18:49:42 +0100 Subject: [PATCH 2/4] Updates tests Signed-off-by: Elena Kolevska --- dapr/clients/http/client.py | 2 +- .../test_http_service_invocation_client.py | 5 +- ...t_secure_http_service_invocation_client.py | 51 ++++--------------- 3 files changed, 14 insertions(+), 44 deletions(-) diff --git a/dapr/clients/http/client.py b/dapr/clients/http/client.py index d0f178b2..3a3d8704 100644 --- a/dapr/clients/http/client.py +++ b/dapr/clients/http/client.py @@ -54,7 +54,7 @@ def get_api_url(self) -> str: return '{}/{}'.format(settings.DAPR_HTTP_ENDPOINT, settings.DAPR_API_VERSION) return 'http://{}:{}/{}'.format(settings.DAPR_RUNTIME_HOST, - settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION) + settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION) async def send_bytes( self, method: str, url: str, diff --git a/tests/clients/test_http_service_invocation_client.py b/tests/clients/test_http_service_invocation_client.py index 587c4d8d..8c53601c 100644 --- a/tests/clients/test_http_service_invocation_client.py +++ b/tests/clients/test_http_service_invocation_client.py @@ -51,9 +51,10 @@ def test_get_api_url_default(self): settings.DAPR_API_VERSION), client.invocation_client._client.get_api_url()) - def test_get_api_url_endpoint_as_argument(self): + @patch.object(settings, "DAPR_HTTP_ENDPOINT", "https://domain1.com:5000") + def test_dont_get_api_url_endpoint_as_argument(self): client = DaprClient("http://localhost:5000") - self.assertEqual('http://localhost:5000/{}'.format(settings.DAPR_API_VERSION), + self.assertEqual('https://domain1.com:5000/{}'.format(settings.DAPR_API_VERSION), client.invocation_client._client.get_api_url()) @patch.object(settings, "DAPR_HTTP_ENDPOINT", "https://domain1.com:5000") diff --git a/tests/clients/test_secure_http_service_invocation_client.py b/tests/clients/test_secure_http_service_invocation_client.py index 704eb0b8..44913294 100644 --- a/tests/clients/test_secure_http_service_invocation_client.py +++ b/tests/clients/test_secure_http_service_invocation_client.py @@ -13,18 +13,13 @@ limitations under the License. """ import ssl +from unittest.mock import patch from dapr.clients.http.client import DaprHttpClient from .certs import CERTIFICATE_CHAIN_PATH from .fake_http_server import FakeHttpServer from dapr.conf import settings from dapr.clients import DaprClient -from dapr.proto import common_v1 -from asyncio import TimeoutError - - -from opencensus.trace.tracer import Tracer # type: ignore -from opencensus.trace import print_exporter, samplers from .test_http_service_invocation_client import DaprInvocationHttpClientTests @@ -45,7 +40,8 @@ def setUp(self): self.server.start() settings.DAPR_HTTP_PORT = self.server_port settings.DAPR_API_METHOD_INVOCATION_PROTOCOL = 'http' - self.client = DaprClient("https://localhost:{}".format(self.server_port)) + settings.DAPR_HTTP_ENDPOINT = "https://localhost:{}".format(self.server_port) + self.client = DaprClient() self.app_id = 'fakeapp' self.method_name = 'fakemethod' self.invoke_url = f'/v1.0/invoke/{self.app_id}/method/{self.method_name}' @@ -55,37 +51,10 @@ def tearDown(self): settings.DAPR_API_TOKEN = None settings.DAPR_API_METHOD_INVOCATION_PROTOCOL = 'http' - def test_global_timeout_setting_is_honored(self): - previous_timeout = settings.DAPR_HTTP_TIMEOUT_SECONDS - settings.DAPR_HTTP_TIMEOUT_SECONDS = 1 - new_client = DaprClient("https://localhost:{}".format(self.server_port)) - self.server.set_server_delay(1.5) - with self.assertRaises(TimeoutError): - new_client.invoke_method(self.app_id, self.method_name, "") - - settings.DAPR_HTTP_TIMEOUT_SECONDS = previous_timeout - - def test_invoke_method_with_tracer(self): - tracer = Tracer(sampler=samplers.AlwaysOnSampler(), exporter=print_exporter.PrintExporter()) - - self.client = DaprClient("https://localhost:{}".format(self.server_port), - headers_callback=lambda: tracer.propagator.to_headers( - tracer.span_context)) - self.server.set_response(b"FOO") - - with tracer.span(name="test"): - req = common_v1.StateItem(key='test') - resp = self.client.invoke_method(self.app_id, self.method_name, http_verb='PUT', - data=req, ) - - request_headers = self.server.get_request_headers() - - self.assertIn('Traceparent', request_headers) - self.assertEqual(b'FOO', resp.data) - - def test_timeout_exception_thrown_when_timeout_reached(self): - new_client = DaprClient("https://localhost:{}".format(self.server_port), - http_timeout_seconds=1) - self.server.set_server_delay(1.5) - with self.assertRaises(TimeoutError): - new_client.invoke_method(self.app_id, self.method_name, "") + @patch.object(settings, "DAPR_HTTP_ENDPOINT", None) + def test_get_api_url_default(self): + client = DaprClient() + self.assertEqual( + 'http://{}:{}/{}'.format(settings.DAPR_RUNTIME_HOST, settings.DAPR_HTTP_PORT, + settings.DAPR_API_VERSION), + client.invocation_client._client.get_api_url()) From 3b7cd7ecffc2e19411bba61031901e07e9b6a19b Mon Sep 17 00:00:00 2001 From: Elena Kolevska Date: Thu, 19 Oct 2023 14:32:53 +0100 Subject: [PATCH 3/4] Updates the docs explaining how http service invocation should be configured Signed-off-by: Elena Kolevska --- daprdocs/content/en/python-sdk-docs/python-client.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/daprdocs/content/en/python-sdk-docs/python-client.md b/daprdocs/content/en/python-sdk-docs/python-client.md index 0b5999a8..8a1ebf5e 100644 --- a/daprdocs/content/en/python-sdk-docs/python-client.md +++ b/daprdocs/content/en/python-sdk-docs/python-client.md @@ -68,6 +68,8 @@ The Python SDK allows you to interface with all of the [Dapr building blocks]({{ ### Invoke a service +The Dapr Python SDK provides a simple API for invoking services via either HTTP or gRPC. The protocol can be selected by setting the `DAPR_API_METHOD_INVOCATION_PROTOCOL` environment variable, defaulting to HTTP when unset. + ```python from dapr.clients import DaprClient @@ -80,6 +82,12 @@ with DaprClient() as d: resp = d.invoke_method('service-to-invoke', 'method-to-invoke', data='{"id":"100", "FirstName":"Value", "LastName":"Value"}', http_verb='post') ``` +The base endpoint for HTTP api calls is specified in the `DAPR_HTTP_ENDPOINT` environment variable. +If this variable is not set, the endpoint value is derived from the `DAPR_RUNTIME_HOST` and `DAPR_HTTP_PORT` variables, whose default values are `127.0.0.1` and `3500` accordingly. + +The base endpoint for gRPC calls is the one used for the client initialisation ([explained above](#initialising-the-client)). + + - For a full guide on service invocation visit [How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}). - Visit [Python SDK examples](https://github.com/dapr/python-sdk/tree/master/examples/invoke-simple) for code samples and instructions to try out service invocation. From 743810c606490af9310a40e0a3efbb816a96c9b6 Mon Sep 17 00:00:00 2001 From: Bernd Verst Date: Tue, 31 Oct 2023 14:34:31 -0700 Subject: [PATCH 4/4] Update daprdocs/content/en/python-sdk-docs/python-client.md Signed-off-by: Bernd Verst --- daprdocs/content/en/python-sdk-docs/python-client.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daprdocs/content/en/python-sdk-docs/python-client.md b/daprdocs/content/en/python-sdk-docs/python-client.md index 8a1ebf5e..304abf09 100644 --- a/daprdocs/content/en/python-sdk-docs/python-client.md +++ b/daprdocs/content/en/python-sdk-docs/python-client.md @@ -68,7 +68,7 @@ The Python SDK allows you to interface with all of the [Dapr building blocks]({{ ### Invoke a service -The Dapr Python SDK provides a simple API for invoking services via either HTTP or gRPC. The protocol can be selected by setting the `DAPR_API_METHOD_INVOCATION_PROTOCOL` environment variable, defaulting to HTTP when unset. +The Dapr Python SDK provides a simple API for invoking services via either HTTP or gRPC (deprecated). The protocol can be selected by setting the `DAPR_API_METHOD_INVOCATION_PROTOCOL` environment variable, defaulting to HTTP when unset. GRPC service invocation in Dapr is deprecated and GRPC proxying is recommended as an alternative. ```python from dapr.clients import DaprClient