Repository navigation
fix(rss): keep empty path segments when resolving feed links - #2698
kevin (kevin9327) wants to merge 2 commits into
Conversation
Bicheng (Kenneth) (BichengWang)
left a comment
There was a problem hiding this comment.
Reviewed head c45c3a2. One correctness regression needs fixing before merge: a network-path reference with leading whitespace loses its authority and is rewritten onto the feed's host.
from urllib.parse import urljoin
from markitdown.converters._rss_converter import _join_url
base = "https://feeds.example.org/news/feed.xml"
reference = " //cdn.example.org/book"
print(urljoin(base, reference)) # https://cdn.example.org/book
print(_join_url(base, reference)) # https://feeds.example.org/bookurlsplit() removes leading whitespace and recognizes ref.netloc, but the delegation condition checks the original reference.startswith("//"). With a space, tab, or newline prefix, that check is false; reconstruction then uses base.netloc and discards cdn.example.org. I also reproduced this through MarkItDown.convert_stream() with RSS description HTML containing <a href=" //cdn.example.org/book">Book</a> and <img src=" //cdn.example.org/cover.png" alt="Cover">: both URLs change to feeds.example.org. This breaks existing links and images even when no repeated slash is involved.
Please delegate references with a parsed authority (ref.netloc) to urljoin, and add whitespace-prefixed network-path cases to the parity and public API coverage. In a temporary probe, that delegation restored all three prefixes while retaining exports//report.csv unchanged.
Validation on macOS / Python 3.12.15: the six additional checks (space/tab/newline through the resolver and public API) pass with main's resolver at 4cc9fa1 and fail on this exact PR head. The existing RSS suite passes all 217 tests, pre-commit run --all-files passes, and git diff --check passes. The full package run was interrupted before completion; other Python versions and Windows were not tested. There were no earlier review findings or inline comments when I checked.
Signed-off-by: J Djs <5299031+kevin9327@users.noreply.github.com>
|
Addressed in 9b6e59c: |
Fixes #2468.
Problem
_resolve_url()usedurllib.parse.urljoin(), whose relative-path merge drops empty path segments (python/cpython#84774). For example,exports/2026//report.csvagainsthttps://example.com/bucket/feed.xmlresolved to.../exports/2026/report.csv, which can be a different object on path-sensitive servers and object stores. Repeated slashes in the base URL (includingxml:base) were collapsed the same way.Change
A small resolver,
_join_url(), in_rss_converter.pyfollows RFC 3986 §5.2 (merge +remove_dot_segments) for the one case urljoin gets wrong: a relative or absolute-path reference against a hierarchical base with a scheme. Everything else goes tourljoinunchanged: empty references, scheme-less or non-hierarchical bases (mailto:,urn:), network-path (//host) references, and references with another scheme. TheValueErrorfallback in_resolve_url()is unchanged. Once the upstream fix lands, this helper can be removed.Tests (
tests/test_rss.py)<a href>and<img src>): empty segments in the reference, in the base path, mixed with.., and in absolute-path references with a query or fragment. 3 of the 4 cases fail onmain.http:gis left out because we keep urljoin's non-strict reading.urljoinfor the delegated cases.Verification
tests/test_rss.py: 217 passed. Full suite (excluding network or service tests): 949 passed, 12 skipped.urljoin(200,000 random base/reference pairs, including dot segments, queries, fragments,//host, other schemes, and non-hierarchical bases): 0 differences when no empty segment is involved. The only differences (16,139) are cases with empty segments, where the new result keeps them.black --checkclean.