Skip to content

Commit e514784

Browse files
committed
Update logic to align with other validation in repository
1 parent b7eec96 commit e514784

File tree

3 files changed

+46
-33
lines changed

3 files changed

+46
-33
lines changed

ldclient/config.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from ldclient.feature_store import InMemoryFeatureStore
1111
from ldclient.hook import Hook
12-
from ldclient.impl.util import log, validate_application_info, is_valid_sdk_key_format
12+
from ldclient.impl.util import log, validate_application_info, validate_sdk_key_format
1313
from ldclient.interfaces import (
1414
BigSegmentStore,
1515
DataSourceUpdateSink,
@@ -261,10 +261,7 @@ def __init__(
261261
:param omit_anonymous_contexts: Sets whether anonymous contexts should be omitted from index and identify events.
262262
:param payload_filter_key: The payload filter is used to selectively limited the flags and segments delivered in the data source payload.
263263
"""
264-
if is_valid_sdk_key_format(sdk_key):
265-
self.__sdk_key = sdk_key
266-
else:
267-
self.__sdk_key = None
264+
self.__sdk_key = validate_sdk_key_format(sdk_key, log)
268265

269266
self.__base_uri = base_uri.rstrip('/')
270267
self.__events_uri = events_uri.rstrip('/')

ldclient/impl/util.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ def timedelta_millis(delta: timedelta) -> float:
2727

2828
__BASE_TYPES__ = (str, float, int, bool)
2929

30+
# Maximum length for SDK keys
31+
_MAX_SDK_KEY_LENGTH = 8192
3032

31-
_retryable_statuses = [400, 408, 429]
33+
_RETRYABLE_STATUSES = [400, 408, 429]
34+
35+
# Compiled regex pattern for valid characters in application values and SDK keys
36+
_VALID_CHARACTERS_REGEX = re.compile(r"[^a-zA-Z0-9._-]")
3237

3338

3439
def validate_application_info(application: dict, logger: logging.Logger) -> dict:
@@ -46,33 +51,33 @@ def validate_application_value(value: Any, name: str, logger: logging.Logger) ->
4651
logger.warning('Value of application[%s] was longer than 64 characters and was discarded' % name)
4752
return ""
4853

49-
if re.search(r"[^a-zA-Z0-9._-]", value):
54+
if _VALID_CHARACTERS_REGEX.search(value):
5055
logger.warning('Value of application[%s] contained invalid characters and was discarded' % name)
5156
return ""
5257

5358
return value
5459

5560

56-
def is_valid_sdk_key_format(sdk_key: str) -> bool:
61+
def validate_sdk_key_format(sdk_key: str, logger: logging.Logger) -> str:
5762
"""
58-
Validates that a string does not contain invalid characters and is not too long for our systems.
63+
Validates that an SDK key does not contain invalid characters and is not too long for our systems.
5964
6065
:param sdk_key: the SDK key to validate
61-
:return: True if the SDK key format is valid, otherwise False
66+
:param logger: the logger to use for logging warnings
67+
:return: the validated SDK key, or None if the SDK key is invalid
6268
"""
6369
if sdk_key is None or sdk_key == '':
64-
return True
65-
66-
if not isinstance(sdk_key, str):
67-
return False
70+
return None
6871

69-
if len(sdk_key) > 8192:
70-
return False
72+
if len(sdk_key) > _MAX_SDK_KEY_LENGTH:
73+
logger.warning('SDK key was longer than %d characters and was discarded' % _MAX_SDK_KEY_LENGTH)
74+
return None
7175

72-
if not re.match(r'^[-a-zA-Z0-9._]+$', sdk_key):
73-
return False
76+
if _VALID_CHARACTERS_REGEX.search(sdk_key):
77+
logger.warning('SDK key contained invalid characters and was discarded')
78+
return None
7479

75-
return True
80+
return sdk_key
7681

7782

7883
def _headers(config):
@@ -128,7 +133,7 @@ def throw_if_unsuccessful_response(resp):
128133

129134
def is_http_error_recoverable(status):
130135
if status >= 400 and status < 500:
131-
return status in _retryable_statuses # all other 4xx besides these are unrecoverable
136+
return status in _RETRYABLE_STATUSES # all other 4xx besides these are unrecoverable
132137
return True # all other errors are recoverable
133138

134139

ldclient/testing/impl/test_util.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from ldclient.impl.util import is_valid_sdk_key_format
1+
import logging
2+
from ldclient.impl.util import validate_sdk_key_format
23

34

4-
def test_is_valid_sdk_key_format_valid():
5+
def test_validate_sdk_key_format_valid():
56
"""Test validation of valid SDK keys"""
7+
logger = logging.getLogger('test')
68
valid_keys = [
79
"sdk-12345678-1234-1234-1234-123456789012",
810
"valid-sdk-key-123",
@@ -12,11 +14,13 @@ def test_is_valid_sdk_key_format_valid():
1214
]
1315

1416
for key in valid_keys:
15-
assert is_valid_sdk_key_format(key) is True
17+
result = validate_sdk_key_format(key, logger)
18+
assert result == key # Should return the same key if valid
1619

1720

18-
def test_is_valid_sdk_key_format_invalid():
21+
def test_validate_sdk_key_format_invalid():
1922
"""Test validation of invalid SDK keys"""
23+
logger = logging.getLogger('test')
2024
invalid_keys = [
2125
"sdk-key-with-\x00-null",
2226
"sdk-key-with-\n-newline",
@@ -27,27 +31,34 @@ def test_is_valid_sdk_key_format_invalid():
2731
]
2832

2933
for key in invalid_keys:
30-
assert is_valid_sdk_key_format(key) is False
34+
result = validate_sdk_key_format(key, logger)
35+
assert result is None # Should return None for invalid keys
3136

3237

33-
def test_is_valid_sdk_key_format_non_string():
38+
def test_validate_sdk_key_format_non_string():
3439
"""Test validation of non-string SDK keys"""
40+
logger = logging.getLogger('test')
3541
non_string_values = [123, object(), [], {}]
3642

3743
for value in non_string_values:
38-
assert is_valid_sdk_key_format(value) is False
44+
result = validate_sdk_key_format(value, logger)
45+
assert result is None # Should return None for non-string values
3946

4047

41-
def test_is_valid_sdk_key_format_empty_and_none():
48+
def test_validate_sdk_key_format_empty_and_none():
4249
"""Test validation of empty and None SDK keys"""
43-
assert is_valid_sdk_key_format("") is True
44-
assert is_valid_sdk_key_format(None) is True
50+
logger = logging.getLogger('test')
51+
assert validate_sdk_key_format("", logger) is None # Empty string should return None
52+
assert validate_sdk_key_format(None, logger) is None # None should return None
4553

4654

47-
def test_is_valid_sdk_key_format_max_length():
55+
def test_validate_sdk_key_format_max_length():
4856
"""Test validation of SDK key maximum length"""
57+
logger = logging.getLogger('test')
4958
valid_key = "a" * 8192
50-
assert is_valid_sdk_key_format(valid_key) is True
59+
result = validate_sdk_key_format(valid_key, logger)
60+
assert result == valid_key # Should return the same key if valid
5161

5262
invalid_key = "a" * 8193
53-
assert is_valid_sdk_key_format(invalid_key) is False
63+
result = validate_sdk_key_format(invalid_key, logger)
64+
assert result is None # Should return None for keys that are too long

0 commit comments

Comments
 (0)