Skip to content

fix(ai): stop percent-encoding slashes in ai.run() model_name#2738

Open
nileshpatil6 wants to merge 1 commit into
cloudflare:mainfrom
nileshpatil6:fix/ai-run-model-name-slash-encoding
Open

fix(ai): stop percent-encoding slashes in ai.run() model_name#2738
nileshpatil6 wants to merge 1 commit into
cloudflare:mainfrom
nileshpatil6:fix/ai-run-model-name-slash-encoding

Conversation

@nileshpatil6

Copy link
Copy Markdown

Fixes #2718

client.ai.run() builds its request path with path_template(), which percent-encodes every character in a path placeholder, including forward slashes. Model names like @cf/meta/llama-3.1-8b-instruct end up in the URL as @cf%2Fmeta%2Fllama-3.1-8b-instruct, and the API responds with a 400 "No route for that URI". This broke every ai.run() call after the v5 rewrite, since v4.3.1 did not encode slashes this way.

Root cause is in src/cloudflare/_utils/_path.py. path_template() treats / as unsafe in the path portion (correct for a normal single path segment, since it protects against path traversal and segment confusion), but model_name is not a single path segment, it is a slash separated identifier that the Cloudflare API expects literally in the URL.

Fix: added support for RFC 6570 reserved expansion syntax in path_template. A placeholder written as {+name} keeps / unescaped in the interpolated value while still percent-encoding every other unsafe character, and the existing dot-segment rejection (. / ..) still runs on the fully assembled path, so this does not weaken the path traversal protection that was added for the normal {name} syntax. Updated the ai.run() path template (both sync and async) to use {+model_name} instead of {model_name}.

I picked the reserved-expansion approach instead of a one-off hack in ai.py because this is a general problem: any path parameter that is itself a multi-segment identifier (this one, and potentially others in the future) needs the same treatment, and RFC 6570 already has a standard operator for exactly this.

Testing:

  • Added test cases to tests/test_utils/test_path.py covering: the reported model_name case, that other special characters (space, ?) are still escaped under {+name}, that the same variable used elsewhere in the same template without + is unaffected, and that dot-segment rejection still fires for {+name}.
  • Ran the full test_path.py suite locally, 56 passed.
  • Ran ruff check and ruff format --diff on the changed files, both clean.
  • Manually reproduced the bug against the module directly before the fix (got @cf%2Fblack-forest-labs%2Fflux-1-schnell) and confirmed the fix produces @cf/black-forest-labs/flux-1-schnell.

client.ai.run() builds its request path with path_template(), which
percent-encodes every character in a path placeholder, including
slashes. Model names like @cf/meta/llama-3.1-8b-instruct end up as
@cf%2Fmeta%2Fllama-3.1-8b-instruct, and the API returns a 400 No route
for that URI error.

Added support for RFC 6570 reserved expansion syntax in path_template
(a placeholder written as {+name} keeps slashes in the interpolated
value unescaped, other characters are still percent-encoded, and
dot-segment rejection still applies). Updated the ai.run() path
template to use {+model_name} instead of {model_name}.

Added test cases for the new {+name} syntax in test_path.py, covering
normal usage, other special characters still being escaped, that the
same variable used elsewhere in the template without + is unaffected,
and that dot-segment protection still triggers.
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.

path_template URL-encodes slashes in model name, breaking ai.run() in v5

1 participant