Skip to content

Commit

Permalink
Fixes http endpoint being overwritten by gRPC address argument in con…
Browse files Browse the repository at this point in the history
…structor (dapr#621)

* Fixes bug of constructor argument being used as http endpoint

Signed-off-by: Elena Kolevska <[email protected]>

* Updates tests

Signed-off-by: Elena Kolevska <[email protected]>

* Updates the docs explaining how http service invocation should be configured

Signed-off-by: Elena Kolevska <[email protected]>

* Update daprdocs/content/en/python-sdk-docs/python-client.md

Signed-off-by: Bernd Verst <[email protected]>

---------

Signed-off-by: Elena Kolevska <[email protected]>
Signed-off-by: Bernd Verst <[email protected]>
Co-authored-by: Bernd Verst <[email protected]>
Signed-off-by: Elena Kolevska <[email protected]>
# Conflicts:
#	dapr/clients/__init__.py
#	dapr/clients/http/client.py
#	dapr/clients/http/dapr_invocation_http_client.py
#	tests/clients/test_http_service_invocation_client.py
#	tests/clients/test_secure_http_service_invocation_client.py
  • Loading branch information
elena-kolevska committed Feb 7, 2024
1 parent 5f85f97 commit 11e372c
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 31 deletions.
5 changes: 2 additions & 3 deletions dapr/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,8 @@ def __init__(
if invocation_protocol == 'HTTP':
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
)
self.invocation_client = DaprInvocationHttpClient(headers_callback=headers_callback,
timeout=http_timeout_seconds)
elif invocation_protocol == 'GRPC':
pass
else:
Expand Down
22 changes: 7 additions & 15 deletions dapr/clients/http/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,10 @@

class DaprHttpClient:
"""A Dapr Http API client"""

def __init__(
self,
message_serializer: 'Serializer',
timeout: Optional[int] = 60,
headers_callback: Optional[Callable[[], Dict[str, str]]] = None,
address: Optional[str] = None,
):
def __init__(self,
message_serializer: 'Serializer',
timeout: Optional[int] = 60,
headers_callback: Optional[Callable[[], Dict[str, str]]] = None):
"""Invokes Dapr over HTTP.
Args:
Expand All @@ -51,17 +47,13 @@ def __init__(
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, settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION
)

return 'http://{}:{}/{}'.format(settings.DAPR_RUNTIME_HOST,
settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION)

async def send_bytes(
self,
Expand Down
10 changes: 4 additions & 6 deletions dapr/clients/http/dapr_invocation_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,16 @@ class DaprInvocationHttpClient:
"""Service Invocation HTTP Client"""

def __init__(
self,
timeout: int = 60,
headers_callback: Optional[Callable[[], Dict[str, str]]] = None,
address: Optional[str] = None,
):
self,
timeout: int = 60,
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,
Expand Down
8 changes: 8 additions & 0 deletions daprdocs/content/en/python-sdk-docs/python-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,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 (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

Expand All @@ -113,6 +115,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.

Expand Down
11 changes: 5 additions & 6 deletions tests/clients/test_http_service_invocation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,11 @@ def test_get_api_url_default(self):
client.invocation_client._client.get_api_url(),
)

def test_get_api_url_endpoint_as_argument(self):
client = DaprClient('http://localhost:5000')
self.assertEqual(
'http://localhost:5000/{}'.format(settings.DAPR_API_VERSION),
client.invocation_client._client.get_api_url(),
)
@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('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')
def test_get_api_url_endpoint_as_env_variable(self):
Expand Down
13 changes: 12 additions & 1 deletion tests/clients/test_secure_http_service_invocation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import ssl
import typing
from asyncio import TimeoutError
from unittest.mock import patch

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
Expand All @@ -27,6 +28,7 @@
from dapr.conf import settings
from dapr.proto import common_v1


from .certs import CERTIFICATE_CHAIN_PATH
from .fake_http_server import FakeHttpServer
from .test_http_service_invocation_client import DaprInvocationHttpClientTests
Expand All @@ -48,7 +50,8 @@ def setUp(self):
self.server.start()
settings.DAPR_HTTP_PORT = self.server_port
settings.DAPR_API_METHOD_INVOCATION_PROTOCOL = 'http'
self.client = DaprClient(f'https://localhost:{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}'
Expand Down Expand Up @@ -114,3 +117,11 @@ def test_timeout_exception_thrown_when_timeout_reached(self):
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())

0 comments on commit 11e372c

Please sign in to comment.