From 870ce71538eb052a37ece30d33a29bab3475a602 Mon Sep 17 00:00:00 2001
From: Moul <moul@moul.re>
Date: Mon, 14 Jun 2021 18:10:02 +0200
Subject: [PATCH] [enh] #170: Define and use precise port regex

---
 duniterpy/api/endpoint.py | 16 ++++++++--------
 duniterpy/constants.py    |  4 ++++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py
index 20690b74..60bd64ed 100644
--- a/duniterpy/api/endpoint.py
+++ b/duniterpy/api/endpoint.py
@@ -143,7 +143,7 @@ BMAEndpointType = TypeVar("BMAEndpointType", bound="BMAEndpoint")
 class BMAEndpoint(Endpoint):
     API = "BASIC_MERKLED_API"
     re_inline = re.compile(
-        f"^{API}(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))?(?: ([0-9]+))$"
+        f"^{API}(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))?(?: ({const.PORT_REGEX}))$"
     )
 
     def __init__(self, server: str, ipv4: str, ipv6: str, port: int) -> None:
@@ -236,7 +236,7 @@ SecuredBMAEndpointType = TypeVar("SecuredBMAEndpointType", bound="SecuredBMAEndp
 class SecuredBMAEndpoint(BMAEndpoint):
     API = "BMAS"
     re_inline = re.compile(
-        f"^{API}(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ([0-9]+)(?: ({const.PATH_REGEX}))?$"
+        f"^{API}(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ({const.PORT_REGEX})(?: ({const.PATH_REGEX}))?$"
     )
 
     def __init__(self, server: str, ipv4: str, ipv6: str, port: int, path: str) -> None:
@@ -317,7 +317,7 @@ WS2PEndpointType = TypeVar("WS2PEndpointType", bound="WS2PEndpoint")
 class WS2PEndpoint(Endpoint):
     API = "WS2P"
     re_inline = re.compile(
-        f"^{API} ({const.WS2PID_REGEX}) ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})|(?:{const.IPV6_REGEX})) ([0-9]+)?(?: ({const.PATH_REGEX}))?$"
+        f"^{API} ({const.WS2PID_REGEX}) ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})|(?:{const.IPV6_REGEX})) ({const.PORT_REGEX})?(?: ({const.PATH_REGEX}))?$"
     )
 
     def __init__(self, ws2pid: str, server: str, port: int, path: str) -> None:
@@ -398,7 +398,7 @@ ESCoreEndpointType = TypeVar("ESCoreEndpointType", bound="ESCoreEndpoint")
 class ESCoreEndpoint(Endpoint):
     API = "ES_CORE_API"
     re_inline = re.compile(
-        f"^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ([0-9]+)$"
+        f"^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ({const.PORT_REGEX})$"
     )
 
     def __init__(self, server: str, port: int) -> None:
@@ -457,7 +457,7 @@ ESUserEndpointType = TypeVar("ESUserEndpointType", bound="ESUserEndpoint")
 class ESUserEndpoint(Endpoint):
     API = "ES_USER_API"
     re_inline = re.compile(
-        "^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ([0-9]+)$"
+        "^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ({const.PORT_REGEX})$"
     )
 
     def __init__(self, server: str, port: int) -> None:
@@ -518,7 +518,7 @@ ESSubscribtionEndpointType = TypeVar(
 class ESSubscribtionEndpoint(Endpoint):
     API = "ES_SUBSCRIPTION_API"
     re_inline = re.compile(
-        f"^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ([0-9]+)$"
+        f"^{API} ((?:{const.HOST_REGEX})|(?:{const.IPV4_REGEX})) ({const.PORT_REGEX})$"
     )
 
     def __init__(self, server: str, port: int) -> None:
@@ -578,7 +578,7 @@ GVAEndpointType = TypeVar("GVAEndpointType", bound="GVAEndpoint")
 
 class GVAEndpoint(Endpoint):
     API = "GVA"
-    endpoint_format = f"^GVA(?: ({const.ENDPOINT_FLAGS_REGEX}))?(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ([0-9]+)(?: ({const.PATH_REGEX}))?$"
+    endpoint_format = f"^GVA(?: ({const.ENDPOINT_FLAGS_REGEX}))?(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ({const.PORT_REGEX})(?: ({const.PATH_REGEX}))?$"
     re_inline = re.compile(endpoint_format)
 
     def __init__(
@@ -707,7 +707,7 @@ GVASUBEndpointType = TypeVar("GVASUBEndpointType", bound="GVASUBEndpoint")
 
 class GVASUBEndpoint(GVAEndpoint):
     API = "GVASUB"
-    endpoint_format = f"^GVASUB(?: ({const.ENDPOINT_FLAGS_REGEX}))?(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ([0-9]+)(?: ({const.PATH_REGEX}))?$"
+    endpoint_format = f"^GVASUB(?: ({const.ENDPOINT_FLAGS_REGEX}))?(?: ({const.HOST_REGEX}))?(?: ({const.IPV4_REGEX}))?(?: ({const.IPV6_REGEX}))? ({const.PORT_REGEX})(?: ({const.PATH_REGEX}))?$"
     re_inline = re.compile(endpoint_format)
 
 
diff --git a/duniterpy/constants.py b/duniterpy/constants.py
index fe1d5cb4..28291184 100644
--- a/duniterpy/constants.py
+++ b/duniterpy/constants.py
@@ -51,6 +51,10 @@ IPV6_REGEX = (
     "4}:){,6}[0-9A-Fa-f]{1,4})?::)(?:%.+)?"
 )
 HOST_REGEX = "[a-z0-9-_.]*(?:.[a-zA-Z])?"
+# https://stackoverflow.com/a/12968117
+PORT_REGEX = (
+    "[1-9]\\d{0,3}|0|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]"
+)
 PATH_REGEX = "[/\\w \\.-]*/?"
 WS2PID_REGEX = "[0-9a-f]{8}"
 WS2P_PRIVATE_PREFIX_REGEX = "O[CT][SAM]"
-- 
GitLab