diff --git a/CHANGELOG.md b/CHANGELOG.md index a715581c..f8dda93f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ### v0.6.x - add: Tutorial for saving live timeseries data (e.g., forecast) in context broker and timeseries database ([#336](https://github.com/RWTH-EBC/FiLiP/pull/363)) - add: Tutorial for using session object ([#370](https://github.com/RWTH-EBC/FiLiP/pull/370)) - +- fix: Addition of trailing slash if missing from base url ([#371](https://github.com/RWTH-EBC/FiLiP/pull/371)) ### v0.6.0 - add: Tutorial for connecting with secured endpoints ([#319](https://github.com/RWTH-EBC/FiLiP/pull/319)) diff --git a/filip/clients/base_http_client.py b/filip/clients/base_http_client.py index f83acee0..44c229ea 100644 --- a/filip/clients/base_http_client.py +++ b/filip/clients/base_http_client.py @@ -16,8 +16,8 @@ class NgsiURLVersion(str, Enum): URL part that defines the NGSI version for the API. """ - v2_url = "/v2" - ld_url = "/ngsi-ld/v1" + v2_url = "v2" + ld_url = "ngsi-ld/v1" class BaseHttpClient: diff --git a/filip/utils/validators.py b/filip/utils/validators.py index c17c5e7c..f3ba6de3 100644 --- a/filip/utils/validators.py +++ b/filip/utils/validators.py @@ -50,7 +50,11 @@ def validate_http_url(url: AnyHttpUrl) -> str: Returns: validated url """ - return str(url) if url else url + url = str(url) if url else url + if url[-1] != "/": + # add trailing slash + url = f"{url}/" + return url @validate_call diff --git a/tests/clients/test_ngsi_ld_cb.py b/tests/clients/test_ngsi_ld_cb.py index f6bc3341..f5dee28a 100644 --- a/tests/clients/test_ngsi_ld_cb.py +++ b/tests/clients/test_ngsi_ld_cb.py @@ -4,10 +4,15 @@ import unittest import logging +from urllib.parse import urljoin + import pyld +from pydantic import AnyHttpUrl from requests import RequestException, Session from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry + +from filip.clients.base_http_client import NgsiURLVersion, BaseHttpClient from filip.clients.ngsi_ld.cb import ContextBrokerLDClient from filip.models.base import FiwareLDHeader, core_context from filip.models.ngsi_ld.context import ( @@ -95,6 +100,26 @@ def test_not_existing_tenant(self): entities = client.get_entity_list() self.assertEqual(len(entities), 0) + def test_url_composition_ld(self): + """ + Test URL composition for ngsi-ld context broker client + """ + user_input_urls = { + "http://example.org/orion/": "http://example.org/orion/ngsi-ld/v1/entities", + "http://example.org/orion": "http://example.org/orion/ngsi-ld/v1/entities", + "http://123.0.0.0:1026": "http://123.0.0.0:1026/ngsi-ld/v1/entities", + "http://123.0.0.0:1026/": "http://123.0.0.0:1026/ngsi-ld/v1/entities", + "http://123.0.0.0/orion": "http://123.0.0.0/orion/ngsi-ld/v1/entities", + "http://123.0.0.0/orion/": "http://123.0.0.0/orion/ngsi-ld/v1/entities", + } + for url in user_input_urls: + url_correct = AnyHttpUrl(user_input_urls[url]) + bhc = BaseHttpClient(url=url) + url_filip = AnyHttpUrl( + urljoin(bhc.base_url, f"{NgsiURLVersion.ld_url.value}/entities") + ) + self.assertEqual(url_correct, url_filip) + def test_get_entities_pagination(self): """ Test pagination of get entities diff --git a/tests/clients/test_ngsi_v2_cb.py b/tests/clients/test_ngsi_v2_cb.py index d967ae85..dad2cfdb 100644 --- a/tests/clients/test_ngsi_v2_cb.py +++ b/tests/clients/test_ngsi_v2_cb.py @@ -12,9 +12,11 @@ import paho.mqtt.client as mqtt from datetime import datetime, timedelta -from urllib.parse import urlparse +from urllib.parse import urlparse, urljoin import requests from requests import RequestException +from pydantic import AnyHttpUrl +from filip.clients.base_http_client import NgsiURLVersion, BaseHttpClient from filip.models.base import FiwareHeader from filip.utils.simple_ql import QueryString from filip.clients.ngsi_v2 import ContextBrokerClient, IoTAClient @@ -104,6 +106,26 @@ def setUp(self) -> None: } ) + def test_url_composition(self): + """ + Test URL composition for context broker client + """ + user_input_urls = { + "http://example.org/orion/": "http://example.org/orion/v2/entities", + "http://example.org/orion": "http://example.org/orion/v2/entities", + "http://123.0.0.0:1026": "http://123.0.0.0:1026/v2/entities", + "http://123.0.0.0:1026/": "http://123.0.0.0:1026/v2/entities", + "http://123.0.0.0/orion": "http://123.0.0.0/orion/v2/entities", + "http://123.0.0.0/orion/": "http://123.0.0.0/orion/v2/entities", + } + for url in user_input_urls: + url_correct = AnyHttpUrl(user_input_urls[url]) + bhc = BaseHttpClient(url=url) + url_filip = AnyHttpUrl( + urljoin(bhc.base_url, f"{NgsiURLVersion.v2_url.value}/entities") + ) + self.assertEqual(url_correct, url_filip) + def test_management_endpoints(self): """ Test management functions of context broker client