Skip to content

Commit c870461

Browse files
committed
fix: validate, clean base url
1 parent ca4fb9a commit c870461

File tree

4 files changed

+71
-14
lines changed

4 files changed

+71
-14
lines changed

mpt_api_client/http/async_client.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from mpt_api_client.constants import APPLICATION_JSON
1212
from mpt_api_client.exceptions import MPTError, transform_http_status_exception
1313
from mpt_api_client.http.client import json_to_file_payload
14+
from mpt_api_client.http.client_utils import validate_base_url
1415
from mpt_api_client.http.types import (
1516
HeaderTypes,
1617
QueryParam,
@@ -38,13 +39,7 @@ def __init__(
3839
"argument to MPTClient."
3940
)
4041

41-
base_url = base_url or os.getenv("MPT_URL")
42-
if not base_url:
43-
raise ValueError(
44-
"Base URL is required. "
45-
"Set it up as env variable MPT_URL or pass it as `base_url` "
46-
"argument to MPTClient."
47-
)
42+
base_url = validate_base_url(base_url or os.getenv("MPT_URL"))
4843
base_headers = {
4944
"User-Agent": "swo-marketplace-client/1.0",
5045
"Authorization": f"Bearer {api_token}",

mpt_api_client/http/client.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
MPTError,
1515
transform_http_status_exception,
1616
)
17+
from mpt_api_client.http.client_utils import validate_base_url
1718
from mpt_api_client.http.types import (
1819
HeaderTypes,
1920
QueryParam,
@@ -51,13 +52,7 @@ def __init__(
5152
"argument to MPTClient."
5253
)
5354

54-
base_url = base_url or os.getenv("MPT_URL")
55-
if not base_url:
56-
raise ValueError(
57-
"Base URL is required. "
58-
"Set it up as env variable MPT_URL or pass it as `base_url` "
59-
"argument to MPTClient."
60-
)
55+
base_url = validate_base_url(base_url or os.getenv("MPT_URL"))
6156
base_headers = {
6257
"User-Agent": "swo-marketplace-client/1.0",
6358
"Authorization": f"Bearer {api_token}",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import re
2+
from typing import Any
3+
from urllib.parse import urlsplit, urlunparse
4+
5+
INVALID_ENV_URL_MESSAGE = "Invalid base URL. Expected scheme://host[:port]"
6+
PATH_TO_REMOVE_RE = re.compile(r"^/$|^/public/?$|^/public/v1/?$")
7+
8+
9+
def validate_base_url(base_url: Any) -> str:
10+
"""Validate base url."""
11+
if not base_url or not isinstance(base_url, str):
12+
raise ValueError(
13+
"Base URL is required. "
14+
"Set it up as env variable MPT_URL or pass it as `base_url` "
15+
"argument to MPTClient."
16+
)
17+
split_result = urlsplit(base_url, scheme="https")
18+
if split_result.scheme and split_result.hostname:
19+
host = (
20+
f"[{split_result.hostname}]" if ":" in split_result.hostname else split_result.hostname
21+
)
22+
port = f":{split_result.port}" if split_result.port else ""
23+
path = PATH_TO_REMOVE_RE.sub("", split_result.path)
24+
return urlunparse((split_result.scheme, f"{host}{port}", path, "", "", ""))
25+
raise ValueError(INVALID_ENV_URL_MESSAGE)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pytest
2+
3+
from mpt_api_client.http.client_utils import validate_base_url
4+
5+
6+
@pytest.mark.parametrize(
7+
("input_url", "expected"),
8+
[
9+
("//[2001:db8:85a3::8a2e:370:7334]:80/a", "https://[2001:db8:85a3::8a2e:370:7334]:80/a"),
10+
("//example.com", "https://example.com"),
11+
("http://example.com", "http://example.com"),
12+
("http://example.com:88/something/else", "http://example.com:88/something/else"),
13+
("http://user@example.com:88/", "http://example.com:88"),
14+
("http://user:pass@example.com:88/", "http://example.com:88"),
15+
("http://example.com/public", "http://example.com"),
16+
("http://example.com/public/", "http://example.com"),
17+
("http://example.com/public/else", "http://example.com/public/else"),
18+
("http://example.com/public/v1", "http://example.com"),
19+
("http://example.com/public/v1/", "http://example.com"),
20+
("http://example.com/else/public", "http://example.com/else/public"),
21+
("http://example.com/elsepublic", "http://example.com/elsepublic"),
22+
],
23+
)
24+
def test_protocol_and_host(input_url, expected):
25+
result = validate_base_url(input_url)
26+
27+
assert result == expected
28+
29+
30+
@pytest.mark.parametrize(
31+
"input_url",
32+
[
33+
"",
34+
"http//example.com",
35+
"://example.com",
36+
"http:example.com",
37+
"http:/example.com",
38+
],
39+
)
40+
def test_protocol_and_host_error(input_url):
41+
with pytest.raises(ValueError):
42+
validate_base_url(input_url)

0 commit comments

Comments
 (0)