pydantic / pydantic/httpx2

Percent encoding `|` in paths

Open Beginner friendly
#896 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.5k
Forks
76
Avg merge
8h 59m
Merged PRs (30d)
24

Description

Originally opened by @nathaniel-daniel on 2025-05-07 23:19:21 in encode/httpx

  • Initially raised as discussion #3479

I got no response, so I'm opening this issue for more visibility.

OS: Windows 11
python --version: Python 3.12.8
httpx version: 0.28.1

I believe the | should be percent encoded in paths, which is not currently the case. If I'm understanding RFC3986 correctly, path characters are pchar, which can be unreserved, pct-encoded, sub-delims, ":", or "@". unreserved can be composed of ALPHA, DIGIT, "-", ".", "_", or "~". pct-encoded is the percent encoding sequences. sub-delims can be "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", or "=". Nowhere in this set is the | character present, meaning it has to be percent-encoded.

Simplifying my problem, httpx seems to call its internal urlparse function to process urls. So, here's an example using that function. This function normally percent-encodes characters as needed, like spaces:

httpx._urlparse.urlparse('http://example.com/ ')

will return

ParseResult(scheme='http', userinfo='', host='example.com', port=None, path='/%20', query=None, fragment=None)

However, this does not happen for |:

httpx._urlparse.urlparse('http://example.com/|')

will return

ParseResult(scheme='http', userinfo='', host='example.com', port=None, path='/|', query=None, fragment=None)

In Firefox and Google Chrome, | is percent-encoded:

encodeURI('http://example.com/|') 

will return

"http://example.com/%7C"

In the requests library, | is also percent-encoded:

requests.utils.requote_uri('http://example.com/|')

will return

'http://example.com/%7C'

The rfc3986 library also percent encodes |:

rfc3986.urlparse('http://example.com/|')

will return

ParseResult(scheme='http', userinfo=None, host='example.com', port=None, path='/%7C', query=None, fragment=None)

Using urllib itself, | also seems to be percent-encoded for path components:

urllib.parse.quote('/|')

will return

'/%7C'

I'm fairly certain that I've interpreted this RFC right, and I think that | should be excluded from the PATH_SAFE set here. Here is its current value: "!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz|~".

Potential Fix: https://github.com/nathaniel-daniel/httpx/commit/a2f327ffbfae967e619e674df9c7c396d644e4d7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in httpx/_urlparse.py at the PATH_SAFE set and reproduce the documented urlparse example with a pipe in the path. Compare the result with the expected percent-encoded form, then verify that paths containing | return %7C without changing the handling of other path characters.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.