From 6c3e066115d0000a13f2c0819fbf0dab5b9054e3 Mon Sep 17 00:00:00 2001 From: Moul <moul@moul.re> Date: Mon, 14 Jun 2021 18:10:12 +0200 Subject: [PATCH] [fix] #170: endpoint: Fix ipv4/host attributes mix up In case only an IPv4 is present, the latter ends up in server/host attribute Since HOST_REGEX is using dots, the IPv4 is matched as a host Only happening to BMA(S) and GVA since the other endpoints' regex are matiching one among (host|ipv6|ipv4) Use ipaddress as a trick after regex matching to switch ipv4 and server/host attributes --- duniterpy/api/endpoint.py | 24 +++++++++++++++++------- tests/api/test_endpoints.py | 12 ++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py index 3ef14708..7d57eb0d 100644 --- a/duniterpy/api/endpoint.py +++ b/duniterpy/api/endpoint.py @@ -14,7 +14,8 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Any, Dict, Optional, Type, TypeVar +from ipaddress import ip_address +from typing import Any, Dict, Optional, Tuple, Type, TypeVar from duniterpy import constants as const @@ -171,10 +172,10 @@ class BMAEndpoint(Endpoint): m = BMAEndpoint.re_inline.match(inline) if m is None: raise MalformedDocumentError(BMAEndpoint.API) - server = m["host"] - ipv4 = m["ipv4"] + server, ipv4 = fix_host_ipv4_mix_up(m["host"], m["ipv4"]) ipv6 = m["ipv6"] port = int(m["port"]) + return cls(server, ipv4, ipv6, port) def inline(self) -> str: @@ -265,11 +266,11 @@ class SecuredBMAEndpoint(BMAEndpoint): m = SecuredBMAEndpoint.re_inline.match(inline) if m is None: raise MalformedDocumentError(SecuredBMAEndpoint.API) - server = m["host"] - ipv4 = m["ipv4"] + server, ipv4 = fix_host_ipv4_mix_up(m["host"], m["ipv4"]) ipv6 = m["ipv6"] port = int(m["port"]) path = m["path"] + if not path: path = "" return cls(server, ipv4, ipv6, port, path) @@ -619,11 +620,11 @@ class GVAEndpoint(Endpoint): if m is None: raise MalformedDocumentError(cls.API) flags = m["flags"] - server = m["host"] - ipv4 = m["ipv4"] + server, ipv4 = fix_host_ipv4_mix_up(m["host"], m["ipv4"]) ipv6 = m["ipv6"] port = int(m["port"]) path = m["path"] + if not flags: flags = "" if not path: @@ -744,3 +745,12 @@ def endpoint(value: Any) -> Any: raise TypeError("Cannot convert {0} to endpoint".format(value)) return result + + +def fix_host_ipv4_mix_up(host: str, ipv4: str) -> Tuple[str, str]: + mixed_up = False + try: + mixed_up = ip_address(host).version == 4 and not ipv4 + except ValueError: + pass + return ("", host) if mixed_up else (host, ipv4) diff --git a/tests/api/test_endpoints.py b/tests/api/test_endpoints.py index 75dc7a61..7198759e 100644 --- a/tests/api/test_endpoints.py +++ b/tests/api/test_endpoints.py @@ -87,3 +87,15 @@ class TestEndpoint(unittest.TestCase): self.assertEqual(gvasub_endpoint.path, "gva") assert gvasub_endpoint.inline(), endpoint_str + + def test_gva_host_ipv4_mix_up(self): + endpoint_str = "GVA S 127.0.0.1 443 gva" + gva_endpoint = endpoint.GVAEndpoint.from_inline(endpoint_str) + self.assertEqual(gva_endpoint.server, "") + self.assertEqual(gva_endpoint.ipv4, "127.0.0.1") + + def test_bmas_host_ipv4_mix_up(self): + endpoint_str = "BMAS 127.0.0.1 443 bma" + bmas_endpoint = endpoint.SecuredBMAEndpoint.from_inline(endpoint_str) + self.assertEqual(bmas_endpoint.server, "") + self.assertEqual(bmas_endpoint.ipv4, "127.0.0.1") -- GitLab