Skip to content

Fix 'api/' endpoint auto-fix of file transfers - #360

Closed
BigRoy wants to merge 1 commit into
bugfix/download-resume-integrityfrom
bugfix/transfer-api-prefix-autofix
Closed

Fix 'api/' endpoint auto-fix of file transfers#360
BigRoy wants to merge 1 commit into
bugfix/download-resume-integrityfrom
bugfix/transfer-api-prefix-autofix

Conversation

@BigRoy

@BigRoy BigRoy commented Sep 12, 2026

Copy link
Copy Markdown
Member

Stacked on #359 (same download/upload loop). Review only the last commit; the base changes to develop once that PR is merged.

Bug

Transfers try to auto-fix endpoints missing the api/ prefix (projects/...api/projects/...), but:

  1. Downloads save the web frontend HTML as the file. The server's web frontend answers unknown non-API urls with 200 and index.html, so the 404/405 check never triggered. download_file("projects/<p>/thumbnails/<id>", path) writes <!DOCTYPE html>... instead of the image, without any error.
  2. The fix consumed a retry attempt. With max_retries=1 the loop ended right after deciding to fix the url, so the fixed request was never sent (the upload raised the original 404, the download silently did nothing).
  3. Upload progress doubled. Content is sent again to the fixed url, but transferred_size was not reset (e.g. 20/10 bytes).
  4. Download stored the fixed url as destination url (set_destination_url) instead of source url.

Fix

  • Also treat a text/html success response from a non-API url as a missing api/ prefix (downloads only; API file endpoints never return HTML).
  • Check whether the url can be fixed before marking it as fixed, and use a while loop where the endpoint fix does not count as an attempt.
  • Reset upload progress when resending to the fixed url; use set_source_url for downloads.

Reproduce

import ayon_api
con = ayon_api.get_server_api_connection()
project_name = "<project>"
thumbnail_id = con.create_thumbnail(project_name, "/path/to/image.png")
con.download_file(f"projects/{project_name}/thumbnails/{thumbnail_id}", "/tmp/out.png")
print(open("/tmp/out.png", "rb").read(15))
# develop: b'<!DOCTYPE html>'
# this PR: b'\x89PNG\r\n\x1a\n...' (and the "Auto-fixed endpoint" warning is logged)

Testing notes

  • Snippet above; also with con.set_max_retries(1).
  • Endpoints with api/ behave as before.
  • tests/test_transfer_api_prefix.py covers the frontend page and upload auto-fix with a single attempt and correct progress.

🤖 Generated with Claude Code

- Web frontend answers unknown urls (without 'api/') with 'index.html'
  and status 200, so the 404 based auto-fix never happened and download
  saved the html page as the file.
- The auto-fix consumed a retry attempt. With 'max_retries' 1 the
  transfer ended without sending the fixed request.
- Upload progress was not reset when content was sent again to fixed
  url, so transferred size was doubled.
- Download stored fixed url as destination url instead of source url.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@BigRoy
BigRoy added this pull request to stack #362 September 12, 2026 22:18
Comment thread ayon_api/server_api.py
# for unknown urls, which is not a file to download.
is_frontend_page = (
response.ok
and "text/html" in response.headers.get(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For me the question is if this is wrong? It has been changed so long ago that anyone using it without the api/ probably already did fix it. I would rather remove the backwards compatibility instead of adding more checks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed.

@BigRoy BigRoy closed this Sep 14, 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