Skip to content

Don't crash on a bracketed IPv6 entry in NO_PROXY - #1242

Closed
NatsUIJM wants to merge 1 commit into
pydantic:mainfrom
NatsUIJM:fix/noproxy-bracketed-ipv6
Closed

NatsUIJM wants to merge 1 commit into
pydantic:mainfrom
NatsUIJM:fix/noproxy-bracketed-ipv6

Conversation

@NatsUIJM

@NatsUIJM NatsUIJM commented Oct 1, 2026 •

Copy link
Copy Markdown

Summary

Recognize bracketed IPv6 literals in NO_PROXY before the hostname-wildcard fallback, preventing valid entries such as [::1] and [::1]:8080 from aborting client construction. all://*[::1] is not a parseable URL pattern, so Client() and AsyncClient() raised InvalidURL: Invalid port: ':1]' before any request was made.

This change does not add general handling for malformed entries, or CIDR/network matching — URLPattern.matches does not consider a prefix length, which is what #969 covers.

Raised in discussion #1241. That thread and this PR were posted together; I am happy to hold the implementation until the thread settles, or to adjust it based on the feedback there.

What changed

  • src/httpx2/httpx2/_utils.py: a bracketed entry whose bracketed part is a bare IPv6 address is recognized before the dispatch, producing the same mount as the unbracketed spelling. The check requires the bracketed part to be the whole address, because is_ipv6_hostname ignores anything after a /.
  • tests/httpx2/test_utils.py: three cases covering [::1], [::1]:8080, [::1]/128.
  • tests/httpx2/client/test_proxies.py: client-construction and transport-selection cases for both client classes, including that [::1]:8080 does not bypass another port, and that [::1] does not bypass another IPv6 address.

Verification

  • Reverting only the _utils.py change fails exactly the three new test_utils.py cases and all twelve test_proxies.py cases; nothing else changes.
  • scripts/check exits 0; full suite 2026 passed, 1 skipped.
  • Local note: this was run on macOS with the system proxy enabled, where urllib.request.getproxies() falls back to scutil and makes the pre-existing test_get_environment_proxies parametrizations fail regardless of this change. To match Linux CI I unset the proxy environment variables and neutralized getproxies_macosx_sysconf via sitecustomize.py. This is not the same as having run on Linux CI.

Separate issue found while testing

Pre-existing, not addressed here: a NO_PROXY entry that names a scheme's default port never matches, because the request URL normalizes that port to None while the pattern keeps it. This affects IPv4 and domain entries as well, and it can also over-match from the other direction. Happy to file it separately.

Checklist

  • I understand that this PR may be closed in case there was no previous discussion.
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.

The documentation box is left unticked: this changes no public API and no documented behaviour contract — it fixes the parsing of an existing configuration. Happy to add a changelog entry or a docs note if the project requires one.

Review in cubic

A `NO_PROXY` entry may spell an IPv6 address the way a URL does, in
brackets, optionally followed by a port or a prefix length. That spelling
does not satisfy `is_ipv6_hostname`, so the entry fell through to the
host-wildcard branch and produced `all://*[::1]`. That is not a parseable
URL pattern, so constructing a client raised `InvalidURL: Invalid port:
':1]'` before any request was made.

Recognize the bracketed form before dispatching, so it produces the same
mount as the unbracketed spelling. This covers a bare address inside the
brackets only - `is_ipv6_hostname` ignores anything after a `/`, so the
check requires the bracketed part to be the whole address.

Entry spellings that are malformed rather than bracketed, such as
`[not:ipv6]`, still reach the wildcard branch, and an entry carrying a
non-numeric port still fails to parse. Both are unchanged here.
@codspeed

codspeed Bot commented Oct 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 17 untouched benchmarks
⏩ 7 skipped benchmarks1


Comparing NatsUIJM:fix/noproxy-bracketed-ipv6 (c4810ed) with main (0286b40)

Open in CodSpeed

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@Kludex

Kludex commented Oct 18, 2026

Copy link
Copy Markdown
Member

Superseded by #1267.

@Kludex Kludex closed this Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants