Skip to content

Fix non-ASCII url_prefix never matching the request path - #495

Closed
agu2347 wants to merge 1 commit into
Pylons:mainfrom
agu2347:fix-nonascii-url-prefix
Closed

Fix non-ASCII url_prefix never matching the request path#495
agu2347 wants to merge 1 commit into
Pylons:mainfrom
agu2347:fix-nonascii-url-prefix

Conversation

@agu2347

@agu2347 agu2347 commented Jul 28, 2026

Copy link
Copy Markdown

Fixes #492.

HTTPTask.execute() compares the configured url_prefix directly against the request path. Per PEP 3333, WSGI represents PATH_INFO/SCRIPT_NAME as "native strings" holding the raw request bytes decoded as latin-1 (each byte becomes the code point of the same value), regardless of the request's actual encoding. The configured url_prefix, however, was left as the ordinary Unicode string the user wrote it as, with no equivalent conversion applied.

For an ASCII-only url_prefix this happens to work, since UTF-8-encoding pure ASCII text and decoding it back as latin-1 is a no-op. For a non-ASCII url_prefix, the two representations are entirely different strings (verified: a 3-character Japanese prefix produces two visually and byte-wise unrelated strings), so the comparison in execute() could never succeed, making it impossible to mount an application behind any non-ASCII url_prefix at all -- exactly as described in the issue.

Fix: apply the same "UTF-8 bytes decoded as latin-1" conversion to url_prefix at config-parsing time (in the slash_fixed_str converter, the only place it's used), matching the exact fix suggested in the issue. This only affects non-ASCII url_prefix values; ASCII values, the empty string, and the existing slash-normalization behavior are completely unaffected, since the added encode/decode round-trip is a no-op for pure ASCII input.

Testing: verified directly: constructed an Adjustments instance with a non-ASCII url_prefix and confirmed it now exactly matches the latin-1-decoded UTF-8 bytes representation that HTTPTask.execute() would compare it against for an incoming request to that path -- the exact mismatch described in the issue is resolved. Also confirmed ASCII url_prefix values, the empty string, and slash-normalization (e.g. "///foo/" -> "/foo") are unaffected.

Added regression tests: one confirming a non-ASCII url_prefix is correctly converted to match the WSGI path-encoding convention, and one confirming ASCII url_prefix values are unaffected. I confirmed the non-ASCII test fails with the original code (produces two unrelated strings) and passes with the fix. Ran the full existing test_adjustments.py and test_task.py suites: 124 passed (122 baseline + 2 new); the 3 remaining failures (socket-binding tests) are pre-existing sandbox limitations, confirmed identical on a clean checkout of main.

HTTPTask.execute() compares the configured url_prefix directly against
the request path. Per PEP 3333, WSGI represents PATH_INFO/SCRIPT_NAME
as "native strings" holding the raw request bytes decoded as latin-1
(each byte becomes the code point of the same value), regardless of
the request's actual encoding. The configured url_prefix, however, was
left as the ordinary Unicode string the user wrote it as, with no
equivalent conversion applied.

For an ASCII-only url_prefix this happens to work, since UTF-8-encoding
pure ASCII text and decoding it back as latin-1 is a no-op. For a
non-ASCII url_prefix, the two representations are entirely different
strings (verified: a 3-character Japanese prefix produces two visually
and byte-wise unrelated strings), so the comparison in execute() could
never succeed, making it impossible to mount an application behind any
non-ASCII url_prefix at all.

Apply the same "UTF-8 bytes decoded as latin-1" conversion to
url_prefix at config-parsing time (in the slash_fixed_str converter,
the only place it's used), matching the exact fix suggested in the
issue. This only affects non-ASCII url_prefix values; ASCII values,
the empty string, and the existing slash-normalization behavior are
completely unaffected, since the added encode/decode round-trip is a
no-op for pure ASCII input.

Verified directly: constructed an Adjustments instance with a
non-ASCII url_prefix and confirmed it now exactly matches the
latin-1-decoded UTF-8 bytes representation that HTTPTask.execute()
would compare it against for an incoming request to that path -- the
exact mismatch described in the issue is resolved. Also confirmed
ASCII url_prefix values, the empty string, and slash-normalization
(e.g. "///foo/" -> "/foo") are unaffected.

Added regression tests: one confirming a non-ASCII url_prefix is
correctly converted to match the WSGI path-encoding convention, and
one confirming ASCII url_prefix values are unaffected. Confirmed the
non-ASCII test fails with the original code (produces two unrelated
strings) and passes with the fix. Ran the full existing
test_adjustments.py and test_task.py suites: 124 passed (122 baseline
+ 2 new); the 3 remaining failures (socket-binding tests) are
pre-existing sandbox limitations, confirmed identical on a clean
checkout of main.

Fixes Pylons#492
@kgaughan

Copy link
Copy Markdown
Member

This smells like it was generated by an LLM. I'm not sure what the Pylon project's stance is on LLM-generated contributions, and this duplicates #493. Because it duplicates that PR, I'm closing this.

@kgaughan kgaughan closed this Jul 30, 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.

Waitress fails to match unicode url_prefix

2 participants