Add downloadURL for storage blob and signed-download URLs

JE
7mo ago
+3687-27

Summary

  • Go: Add AccountClient.DownloadURL() for fetching file content from any API-routable download URL (storage blob URLs from <bc-attachment> elements, etc.). Two-hop flow: URL rewriting → authenticated API request (captures 302) → unauthenticated fetch of signed download URL. Extracts duplicated bare-transport logic from UploadsService.Download into shared Client.fetchSignedDownload.
  • TypeScript: Add client.downloadURL() with the same semantics. Operation hooks fire once; request hooks fire for the API leg only. No retry/cache — streaming downloads aren't safely retryable. Non-null body guarantee with fail-fast on pathological bodyless responses.

Test plan

  • Go: 18 tests covering validation, URL rewriting, host-agnostic inputs, query preservation, redirect flow, direct download, relative Location resolution, redirect without Location, API errors (404/403/500), S3 errors, auth header isolation, request hooks (start+end API-only), operation hooks, gate rejection, upload download regression (no auth on S3, no timeout)
  • TypeScript: 30 tests covering the same surface via MSW — plus network failure on both hops, 429 no-retry, and hook error payloads
  • make check passes (all SDKs, conformance, linting, drift checks)

Summary by cubic

Adds a two-hop file download API across Go, TypeScript, Ruby, Kotlin, and Swift to fetch storage blob and other API-routable URLs, following redirects to signed URLs and streaming the response. Also refactors Go download logic to a shared helper and tightens validation, redirect handling, and streaming timeouts.

  • New Features

    • All SDKs (Go/TS/Ruby/Kotlin/Swift): Add downloadURL with a common flow — rewrite to API → authenticated first hop (captures 301/302/303/307/308) → unauthenticated fetch of the signed URL. Streaming-safe, returns content type/length/filename. Operation hooks fire once; request hooks fire on the API hop only. No retries.
    • Go: Extract shared fetchSignedDownload for signed URLs; API hop uses Timeout: 0 for direct streaming. Swift/Ruby/Kotlin add no-redirect first-hop support (dataNoRedirect in Swift, get_no_retry in Ruby, redirect-disabled client in Kotlin).
  • Bug Fixes

    • Narrowed redirect handling to true redirects and tightened protocol validation.
    • TypeScript: Parse Content-Length defensively; cancel signed-URL bodies on non-OK to free connections.
    • Kotlin: Match SDK error parsing for downloadURL by reading JSON error/error_description and Retry-After headers.
    • Go uploads: UploadsService.Download now uses the shared helper, ensuring no auth headers and no client-level timeout on the signed-URL hop.