Repository navigation
fix(lab-ops-hub): return empty path, userinfo and ?/# markers WHATWG-normalized (#639) - #648
Conversation
…normalized (#639) validate_crawl_url returned http://example.com with an empty path, http://@example.com/ with an empty userinfo, and dropped empty ? / # markers, while the Worker validator returns the WHATWG form (http://example.com/, http://example.com/, markers kept), so the two crawlers recorded different URLs for the same target. - _normalize_validated_url now supplies "/" for an empty path and drops an empty userinfo's "@" (the empty port's colon was already dropped by the #633 port canonicalization). - New _empty_query_fragment_markers carries the empty ? / # markers urlparse cannot represent as a suffix re-attached after each geturl() rebuild — in _normalize_validated_url, in _url_with_encoded_components, and in _url_with_host (which rebuilds percent-decoded and canonical-IP URLs before normalization). Decision on the markers: preserve them, matching the Worker byte for byte. - No verdict changes: which targets are accepted or refused is untouched. Tests: new Python battery (empty path/port/userinfo, markers, percent-decoded and IP-literal rebuilds, redirect-handler pin, blocked controls) + TS pin of the Worker reference forms. Python 55/55, TS 38/38; ablation exact (only the new Python test fails with app.py reverted). Differential vs the Worker under Bun over 43,200 generated spellings (host x userinfo x port x path x query/fragment tails x scheme): zero differences in this issue's scope — the only remaining diffs are the deliberate IDN host spelling (#529/#633) and the percent-encoded root dot tracked separately in #647.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing: 3
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bd77d0937
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| path=resolved_path, | ||
| params="", | ||
| ).geturl() | ||
| ).geturl() + _empty_query_fragment_markers(url) |
There was a problem hiding this comment.
Insert the empty query marker before the fragment
When an accepted URL has an empty query followed by a non-empty fragment, such as http://example.com/path?#frag, geturl() first produces http://example.com/path#frag and this suffix append then returns http://example.com/path#frag?. The ? has consequently become fragment data instead of preserving the empty query, diverging from the Worker/WHATWG result http://example.com/path?#frag; the marker must be inserted before the fragment rather than appended to the whole serialization.
Useful? React with 👍 / 👎.
Fixes #639
Problem
validate_crawl_url(container,pkgs/lab-ops-hub/container/app.py) returned three spellings without the WHATWG normalizations the Worker validator applies, so the two crawlers recorded different URLs for the same accepted target:http://example.comhttp://example.comhttp://example.com/http://example.com:8080http://example.com:8080http://example.com:8080/http://@example.com/http://@example.com/http://example.com/http://example.com/path?http://example.com/pathhttp://example.com/path?http://example.com/path#http://example.com/pathhttp://example.com/path#(The fourth arm from the issue, the empty port
http://example.com:/path, was already fixed by #633's port canonicalization and is pinned by the new test.)Solution
_normalize_validated_urlsupplies/for an empty path and drops an empty userinfo's@._empty_query_fragment_markershelper:urlparsecannot represent an empty query or fragment (it parses.../path?and.../pathidentically andgeturl()drops the marker), so the markers are computed from the spelling and re-attached as a suffix after eachgeturl()rebuild — in_normalize_validated_url, in_url_with_encoded_components, and in_url_with_host, which rebuilds percent-decoded-host and canonical-IP URLs before normalization and would otherwise drop the markers before the normalizer sees them (caught by the differential fuzz below). Decision on the markers, as the issue asked: preserve them, matching the Worker byte for byte; a?inside the fragment stays data.Verification
test_returns_empty_components_normalized: the issue battery plus percent-decoded (%65xample.com) and IP-literal (8%2e8%2e8%2e8,134744072) rebuilds,?-in-fragment data controls, blocked controls, and a redirect-handler pin. New TS test pins the Worker reference forms.app.pyreverted, only the new Python test fails.example.com%2e) tracked separately in lab-ops-hub: container validator drops the DNS root dot only for the percent-encoded spelling — returned URL differs from the Worker and from its own literal-dot form #647 — that issue's spellings are unchanged by this PR.ruff formatapplied; diff confined to the validator helpers and the two test files.Single-repo: the validator pair exists only in this repo (no copy in developing-today/opencode, developing-today/openchamber, or dezren39/nix).
Need help on this PR? Tag
@codesmith-botwith what you need.