Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(_streaming_download): handle retry-level JSON error responses #2329

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

cfm
Copy link
Member

@cfm cfm commented Dec 11, 2024

Status

Ready for review.

Description

Fixes #2232 by checking for JSON responses the proxy may have returned midstream in a Range retry, not only at the very beginning of the expected response.

#2330 is a limitation of the test suite I've discovered in the course of this investigation. It's out of the scope of this fix.

Test Plan

  • make regenerate-sdk-cassettes succeeds against unparameterized make dev.
    • NB. This is most of this very large diff. Filter to just .py files for easier review!
  • Basic smoke-testing of the Client (via this SDK) with any SecureDrop Server.
    • Files can be downloaded.

Checklist

If these changes modify code paths involving cryptography, the opening of files in VMs or network (via the RPC service) traffic, Qubes testing in the staging environment is required. For fine tuning of the graphical user interface, testing in any environment in Qubes is required. Please check as applicable:

  • I have tested these changes in the appropriate Qubes environment
  • I do not have an appropriate Qubes OS workstation set up (the reviewer will need to test these changes)
  • These changes should not need testing in Qubes

If these changes add or remove files other than client code, the AppArmor profile may need to be updated. Please check as applicable:

  • I have updated the AppArmor profile
  • No update to the AppArmor profile is required for these changes
  • I don't know and would appreciate guidance

If these changes modify the database schema, you should include a database migration. Please check as applicable:

  • I have written a migration and upgraded a test database based on main and confirmed that the migration is self-contained and applies cleanly
  • I have written a migration but have not upgraded a test database based on main and would like the reviewer to do so
  • I need help writing a database migration
  • No database schema changes are needed

@cfm cfm self-assigned this Dec 11, 2024
@cfm cfm added this to the 0.15.0 milestone Dec 11, 2024
@cfm cfm force-pushed the 2232-error-on-retry branch from 01201a7 to 3b27867 Compare December 11, 2024 23:26
@cfm cfm marked this pull request as ready for review December 11, 2024 23:47
@cfm cfm requested a review from a team as a code owner December 11, 2024 23:47
if contents[0:1] == b"{":
logger.error(f"Retry {retry}, received JSON error response.")
return self._handle_json_response(contents)
# ...and then at the retry level:
partial = contents[bytes_written_prev:bytes_written]
Copy link
Member

Choose a reason for hiding this comment

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

Should/can we skip this check if bytes_written_prev == 0 (a no-retry request)?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wondered about this. In terms of control flow:

  1. In a retry request:
    1. bytes_written_prev < len(contents) and
    2. bytes_written = len(contents), so
    3. len(partial) < len(contents), so
    4. partial[0:1] != contents[0:1] and is worth checking,
    5. unless we've already returned on line 220.
  2. In a non-retry request:
    1. bytes_written_prev = 0 and
    2. bytes_written = len(contents), so
    3. len(partial) == len(contents), so
    4. partial[0:1] == contents[0:1] and is indeed redundant,
    5. unless we've already returned on line 220.

So the "should" here for me comes down to: Is this check too expensive to do twice for a successful request? Probably not. But it is confusing, so let me make it explicit.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in c5d0b87. I've kept the conditionals parallel between contents and partial, but let me know if you'd prefer a nested one for partial.

@cfm cfm force-pushed the 2232-error-on-retry branch from 3b27867 to 7448448 Compare December 12, 2024 20:41
cfm added 2 commits December 12, 2024 12:41
…uest halfway through actual file-size

Now that we can respond correctly to retry-level errors, this change
should allow running "make regenerate-sdk-cassettes" on any valid "make
dev" instance, not only one with submissions above a hard-coded
file-size.
@cfm cfm force-pushed the 2232-error-on-retry branch from 7448448 to d233eb3 Compare December 12, 2024 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

API._streaming_download() does not handle HTTP 416 Range Not Satisfiable errors
2 participants