Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions connect/customer/content_matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def _find_best_matching_content(
) -> _ContentBlock | None:
parsed = urllib.parse.urlparse(resource_url)
host = parsed.netloc
path = parsed.path
path = parsed.path or "/"
if not parsed.scheme or not host:
debug_log(debug, f"Cannot parse resource URL: {resource_url}")
return None
Expand All @@ -25,23 +25,30 @@ def _find_best_matching_content(
best_specificity = -1

for block in content_blocks:
pattern = urllib.parse.urlparse(block.url_pattern)
if not pattern.scheme or not pattern.netloc:
debug_log(debug, f"Skipping block with invalid URL pattern: {block.url_pattern}")
continue

if pattern.netloc != host:
debug_log(
debug,
f"Skipping block: host mismatch (pattern={pattern.netloc}, resource={host})",
)
continue

if pattern.path == path:
is_path_only = block.url_pattern.startswith("/")

if is_path_only:
pattern_path = block.url_pattern
else:
pattern = urllib.parse.urlparse(block.url_pattern)
if not pattern.scheme or not pattern.netloc:
debug_log(debug, f"Skipping block with invalid URL pattern: {block.url_pattern}")
continue

if pattern.netloc != host:
debug_log(
debug,
f"Skipping block: host mismatch (pattern={pattern.netloc}, resource={host})",
)
continue

pattern_path = pattern.path or "/"

if pattern_path == path:
debug_log(debug, f"Exact match found: {block.url_pattern}")
return block

specificity = _score_path_pattern(pattern.path or "/", path or "/")
specificity = _score_path_pattern(pattern_path, path)
if specificity > best_specificity:
best_specificity = specificity
best_match = block
Expand Down
62 changes: 62 additions & 0 deletions tests/customer/test_content_matcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,68 @@ def test_find_best_matching_content_handles_port_specific_host_matching() -> Non
assert _find_best_matching_content(blocks, "http://localhost:3001/page") is None


def test_find_best_matching_content_matches_path_only_pattern() -> None:
"""Path-only patterns (starting with /) match regardless of host."""
blocks = [
_ContentBlock(url_pattern="/article/*", server="http://127.0.0.1:8787", license_xml="<license/>"),
]

match = _find_best_matching_content(blocks, "http://127.0.0.1:7676/article/foo")

assert match is not None
assert match.url_pattern == "/article/*"

Comment thread
ranael-garem marked this conversation as resolved.

def test_find_best_matching_content_exact_path_only_wins_over_wildcard() -> None:
"""Exact path-only match beats a path-only wildcard."""
blocks = [
_ContentBlock(url_pattern="/*", server="http://127.0.0.1:8787", license_xml="<license/>"),
_ContentBlock(url_pattern="/article/foo", server="http://127.0.0.1:8787", license_xml="<license/>"),
]

match = _find_best_matching_content(blocks, "http://127.0.0.1:7676/article/foo")

assert match is not None
assert match.url_pattern == "/article/foo"


def test_find_best_matching_content_path_only_matches_any_host() -> None:
"""Path-only patterns match any host."""
blocks = [
_ContentBlock(url_pattern="/article/*", server="http://127.0.0.1:8787", license_xml="<license/>"),
]

match = _find_best_matching_content(blocks, "http://totally-different-host.com/article/foo")

assert match is not None
assert match.url_pattern == "/article/*"


def test_find_best_matching_content_mixes_full_url_and_path_only() -> None:
"""Path-only pattern with higher specificity wins over full-URL pattern."""
blocks = [
_ContentBlock(url_pattern="http://127.0.0.1:7676/*", server="http://127.0.0.1:8787", license_xml="<license/>"),
_ContentBlock(url_pattern="/article/*", server="http://127.0.0.1:8787", license_xml="<license/>"),
]

match = _find_best_matching_content(blocks, "http://127.0.0.1:7676/article/foo")

assert match is not None
assert match.url_pattern == "/article/*"


def test_find_best_matching_content_matches_root_url_without_trailing_slash() -> None:
"""A resource URL with no path (e.g. http://host) matches a / pattern."""
blocks = [
_ContentBlock(url_pattern="/", server="http://127.0.0.1:8787", license_xml="<license/>"),
]

match = _find_best_matching_content(blocks, "http://127.0.0.1:7676")

assert match is not None
assert match.url_pattern == "/"


def test_find_best_matching_content_returns_none_for_empty_blocks() -> None:
"""Returns None when no content blocks are provided."""
assert _find_best_matching_content([], "http://example.com/page") is None
Expand Down
Loading