kopia lustrzana https://github.com/Yakifo/amqtt
Fix topic filter matching
- re.escape() the whole filter string first to escape _all_ regex metacharacters in it, not just $. (# and + are both regex metacharacters, so their replace expressions now need a leading \\ to replace the escaping, too.) - # matches topics both with and without a trailing /, so the replace expressions adds a '?' before the '.*'. The .lstrip('?') at the end removes this in case the # was the first character in the filter. - + should only match a single level, but it should _also_ match empty levels, so use '[^/]*' to replace it. - Use Regex.fullmatch() to match against the whole topic string, not just its start. Also add two unit tests to test this matching, and fix an incorrect match against + in test_client_subscribe_publish_dollar_topic_2.pull/42/head
rodzic
7921e2cc22
commit
c41b01499d
|
@ -847,11 +847,12 @@ class Broker:
|
|||
else:
|
||||
# else use regex
|
||||
match_pattern = re.compile(
|
||||
a_filter.replace("#", ".*")
|
||||
.replace("$", "\$")
|
||||
.replace("+", "[/\$\s\w\d]+")
|
||||
re.escape(a_filter)
|
||||
.replace("\\#", "?.*")
|
||||
.replace("\\+", "[^/]*")
|
||||
.lstrip("?")
|
||||
)
|
||||
return match_pattern.match(topic)
|
||||
return match_pattern.fullmatch(topic)
|
||||
|
||||
async def _broadcast_loop(self):
|
||||
running_tasks = deque()
|
||||
|
|
|
@ -446,7 +446,7 @@ async def test_client_subscribe_publish_dollar_topic_2(broker):
|
|||
ret = await sub_client.subscribe([("+/monitor/Clients", QOS_0)])
|
||||
assert ret == [QOS_0]
|
||||
|
||||
await _client_publish("/test/monitor/Clients", b"data", QOS_0)
|
||||
await _client_publish("test/monitor/Clients", b"data", QOS_0)
|
||||
message = await sub_client.deliver_message()
|
||||
assert message is not None
|
||||
|
||||
|
@ -500,3 +500,39 @@ async def _client_publish(topic, data, qos, retain=False):
|
|||
ret = await pub_client.publish(topic, data, qos, retain)
|
||||
await pub_client.disconnect()
|
||||
return ret
|
||||
|
||||
|
||||
def test_matches_multi_level_wildcard(broker):
|
||||
test_filter = "sport/tennis/player1/#"
|
||||
|
||||
for bad_topic in [
|
||||
"sport/tennis",
|
||||
"sport/tennis/",
|
||||
]:
|
||||
assert not broker.matches(bad_topic, test_filter)
|
||||
|
||||
for good_topic in [
|
||||
"sport/tennis/player1",
|
||||
"sport/tennis/player1/",
|
||||
"sport/tennis/player1/ranking",
|
||||
"sport/tennis/player1/score/wimbledon",
|
||||
]:
|
||||
assert broker.matches(good_topic, test_filter)
|
||||
|
||||
|
||||
def test_matches_single_level_wildcard(broker):
|
||||
test_filter = "sport/tennis/+"
|
||||
|
||||
for bad_topic in [
|
||||
"sport/tennis",
|
||||
"sport/tennis/player1/",
|
||||
"sport/tennis/player1/ranking",
|
||||
]:
|
||||
assert not broker.matches(bad_topic, test_filter)
|
||||
|
||||
for good_topic in [
|
||||
"sport/tennis/",
|
||||
"sport/tennis/player1",
|
||||
"sport/tennis/player2",
|
||||
]:
|
||||
assert broker.matches(good_topic, test_filter)
|
||||
|
|
Ładowanie…
Reference in New Issue