Skip to content

Commit 0af3404

Browse files
committed
Add namespace value to TokenRedis source
1 parent 5989d31 commit 0af3404

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

tests/test_token_plugins.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,29 @@
77
from unittest.mock import patch, mock_open, MagicMock
88
from jwcrypto import jwt, jwk
99

10-
from websockify.token_plugins import ReadOnlyTokenFile, JWTTokenApi, TokenRedis
10+
from websockify.token_plugins import parse_source_args, ReadOnlyTokenFile, JWTTokenApi, TokenRedis
11+
12+
class ParseSourceArgumentsTestCase(unittest.TestCase):
13+
def test_parameterized(self):
14+
params = [
15+
('', ['']),
16+
(':', ['', '']),
17+
('::', ['', '', '']),
18+
('"', ['"']),
19+
('""', ['""']),
20+
('"""', ['"""']),
21+
('"localhost"', ['localhost']),
22+
('"localhost":', ['localhost', '']),
23+
('"localhost"::', ['localhost', '', '']),
24+
('"local:host"', ['local:host']),
25+
('"local:host:"pass"', ['"local', 'host', "pass"]),
26+
('"local":"host"', ['local', 'host']),
27+
('"local":host"', ['local', 'host"']),
28+
('localhost:6379:1:pass"word:"my-app-namespace:dev"',
29+
['localhost', '6379', '1', 'pass"word', 'my-app-namespace:dev']),
30+
]
31+
for src, args in params:
32+
self.assertEqual(args, parse_source_args(src))
1133

1234
class ReadOnlyTokenFileTestCase(unittest.TestCase):
1335
patch('os.path.isdir', MagicMock(return_value=False))
@@ -402,6 +424,15 @@ def test_src_with_host_empty_port_empty_db_empty_pass_namespace(self):
402424
self.assertEqual(plugin._password, None)
403425
self.assertEqual(plugin._namespace, "namespace:")
404426

427+
def test_src_with_host_empty_port_empty_db_empty_pass_nested_namespace(self):
428+
plugin = TokenRedis('127.0.0.1::::"ns1:ns2"')
429+
430+
self.assertEqual(plugin._server, '127.0.0.1')
431+
self.assertEqual(plugin._port, 6379)
432+
self.assertEqual(plugin._db, 0)
433+
self.assertEqual(plugin._password, None)
434+
self.assertEqual(plugin._namespace, "ns1:ns2:")
435+
405436
def test_src_with_host_empty_port_db_no_pass_no_namespace(self):
406437
plugin = TokenRedis('127.0.0.1::2')
407438

websockify/token_plugins.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@
77

88
logger = logging.getLogger(__name__)
99

10+
_SOURCE_SPLIT_REGEX = re.compile(
11+
r'(?<=^)"([^"]+)"(?=:|$)'
12+
r'|(?<=:)"([^"]+)"(?=:|$)'
13+
r'|(?<=^)([^:]*)(?=:|$)'
14+
r'|(?<=:)([^:]*)(?=:|$)',
15+
)
16+
17+
18+
def parse_source_args(src):
19+
"""It works like src.split(":") but with the ability to use a colon
20+
if you wrap the word in quotation marks.
21+
22+
a:b:c:d -> ['a', 'b', 'c', 'd'
23+
a:"b:c":c -> ['a', 'b:c', 'd']
24+
"""
25+
matches = _SOURCE_SPLIT_REGEX.findall(src)
26+
return [m[0] or m[1] or m[2] or m[3] for m in matches]
27+
1028

1129
class BasePlugin():
1230
def __init__(self, src):
@@ -197,6 +215,10 @@ class TokenRedis(BasePlugin):
197215
198216
my-redis-host::::my-app-namespace
199217
218+
Or if your namespace is nested, you can wrap it in quotes:
219+
220+
my-redis-host::::"first-ns:second-ns"
221+
200222
In the more general case you will use:
201223
202224
my-redis-host:6380:1:verysecretpass:my-app-namespace
@@ -241,7 +263,7 @@ def __init__(self, src):
241263
self._password = None
242264
self._namespace = ""
243265
try:
244-
fields = src.split(":")
266+
fields = parse_source_args(src)
245267
if len(fields) == 1:
246268
self._server = fields[0]
247269
elif len(fields) == 2:

0 commit comments

Comments
 (0)