Skip to content

Percent-encode literal template text per RFC 6570 Section 3.1#153

Open
gaoflow wants to merge 1 commit into
python-hyper:mainfrom
gaoflow:encode-literal-text
Open

Percent-encode literal template text per RFC 6570 Section 3.1#153
gaoflow wants to merge 1 commit into
python-hyper:mainfrom
gaoflow:encode-literal-text

Conversation

@gaoflow

@gaoflow gaoflow commented Jul 16, 2026

Copy link
Copy Markdown

RFC 6570 Section 3.1 requires literal text (the characters outside of {...} expressions) that is not allowed in a URI to be copied to the result as its UTF-8 percent-encoded octets. uritemplate copies literals verbatim, so non-ASCII literal text is emitted unencoded:

>>> from uritemplate import URITemplate
>>> URITemplate("café/{var}").expand(var="value")
'café/value'          # RFC 6570 §3.1 requires 'caf%C3%A9/value'

_expand relied on a single template_re.sub() pass, which copies everything outside an expression as-is. It now encodes each literal run around the expanded expressions in one left-to-right pass. A single sub cannot do this, because re-quoting the whole result afterwards would double-encode the expansion output. Existing %XX triplets inside a literal are preserved, so already-encoded literals (x%20y/{var}) and partial-expansion round-trips stay stable.

This is pinned by the official uritemplate-test "Additional Examples 8: Literal Encoding" group, which was absent from the bundled fixtures; it is added here, along with unit tests for the multibyte, reserved-character, and pre-encoded boundaries. The full upstream suite (spec examples, by-section, and extended tests) passes.

Literal characters outside of expressions were copied verbatim during
expansion, so a non-ASCII literal such as the accented e in "cafe/{var}"
was emitted raw instead of percent-encoded. RFC 6570 Section 3.1 requires
literal text that is not URI-legal to be encoded as its UTF-8
percent-encoded triplets.

_expand now encodes each literal run around the expanded expressions
instead of relying on a single re.sub pass, which cannot do this without
re-encoding the already-encoded expansion output. Existing percent-encoded
triplets in the literal are preserved. This matches the official
uritemplate-test "Literal Encoding" cases, added here to the bundled
fixtures.
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.

1 participant