Skip to content

LOC-7549: decode gzip binary downloads and report the real binding version - #71

Open
07souravkunda wants to merge 1 commit into
masterfrom
LOC-7549/gzip-binary-download
Open

07souravkunda wants to merge 1 commit into
masterfrom
LOC-7549/gzip-binary-download

Conversation

@07souravkunda

Copy link
Copy Markdown
Collaborator

Summary

Two fixes, so the C# binding can be moved onto the gzip-encoded binary download (about 3.3× less CDN egress):

  1. downloadBinary decodes Content-Encoding: gzip. It previously used WebClient.DownloadFile, which writes the response bytes as received, so a gzip-encoded binary would be saved compressed and fail to start. It now uses HttpClient with AutomaticDecompression = GZip | Deflate, the same client type fetchSourceUrl already uses, and streams the response to disk. The proxy handling is unchanged, and a partial file is deleted if the download fails.
  2. The binding reports its real version in the User-Agent. GenerateAssemblyInfo has been false since the 2020 SDK-style csproj migration (d14811c), and the library has no AssemblyInfo.cs. As a result, <AssemblyVersion> never reached the DLL, and every release has sent User-Agent: browserstack-local-csharp/0.0.0000.0000. In the 7 days to 2026-10-26, that was 5,462 of the 5,464 C# calls to /binary/api/v1/endpoint; the other 2 sent no version. With the attribute generated, this release reports e.g. browserstack-local-csharp/3.1.0001.0000.

JIRA: https://browserstack.atlassian.net/browse/LOC-7549
Related:

  • browserstack/local-service#706: hands latest_gzip to bindings that decode it. For C#, only when the reported version isn't 0.0.
  • browserstack/local-binaries-for-deploy#73: publishes latest_gzip/.

Why the version fix is needed

latest_gzip/ objects are stored with Content-Encoding: gzip, and S3/CloudFront send gzip whatever Accept-Encoding the client sends. local-service must therefore give that path only to C# builds that contain fix 1. Every release in the field reports 0.0.0000.0000, so without fix 2 the new release would be indistinguishable from the old ones. With it:

User-Agent local-service returns
browserstack-local-csharp/0.0.0000.0000 (all current releases) latest_unzip (unchanged)
browserstack-local-csharp / …/Unknown latest_unzip
browserstack-local-csharp/3.1.0001.0000 and later (this change) latest_gzip, once the flag is on

Not in this PR

The version bump and release are left to the release branch, as usual.

Testing

  • dotnet test "BrowserStackLocal Unit Tests" (.NET 6, macOS): 35 passed, 0 failed. The new tests are:
    • TestDownloadBinaryDecodesGzipContentEncoding: a local HttpListener serves a 2 MB binary with Content-Encoding: gzip, and the saved file must equal the original bytes;
    • TestDownloadBinarySavesUncompressedResponseAsIs: a plain response is saved unchanged;
    • TestDownloadBinaryFailureLeavesNoPartialFile: a 404 throws and leaves no file;
    • TestBindingVersionComesFromTheAssembly: the assembly version isn't 0.0.0.0 and flows into GetVersionStringFromAssemblyEmbedded.
  • Both fixes are covered by a failing test:
    • restoring the original WebClient download makes the gzip test fail;
    • restoring GenerateAssemblyInfo=false makes the version test fail.
  • End-to-end: the patched downloadBinary() was pointed at a gzip-encoded staging copy of the 8.9 darwin binary on CloudFront (binaries/LOC-7549_gzip_poc/, 10,156,640 B on the wire). It saved 36,317,952 B with the prod SHA-256 (9091089b…), and --version printed BrowserStack Local version 8.9.
  • Not yet run here: the Windows msbuild build and integration tests in CI.

🤖 Generated with Claude Code

…rsion

downloadBinary used WebClient.DownloadFile, which never decodes
Content-Encoding. The binary download endpoint is moving gzip-capable
bindings to binaries/release/latest_gzip, whose objects are stored with
Content-Encoding: gzip and served gzip regardless of Accept-Encoding,
so this binding would have saved the gzip stream as the binary. It now
downloads with HttpClient + AutomaticDecompression (GZip | Deflate),
streams to disk, honours the same proxy, and deletes a partial file if
the download fails.

GenerateAssemblyInfo was false (since the 2020 SDK-style csproj move)
and the library has no AssemblyInfo, so the csproj <AssemblyVersion>
never reached the DLL: every release reported User-Agent
browserstack-local-csharp/0.0.0000.0000 (5,462 of 5,464 C# endpoint
calls in the 7 days to 2026-10-26). Generating it lets local-service
tell this release, which decodes gzip, from older ones that must keep
the uncompressed path.

Tests:
- downloadBinary against a local HttpListener: gzip-encoded response
  saved decoded, plain response saved as-is, 404 leaves no file.
- assembly version is generated and flows into the version string.
Both new tests fail on the pre-change code. Also run against the
staged gzip object on CloudFront: 36,317,952 B, prod SHA-256,
`--version` 8.9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Central YAML (base), Organization UI (inherited), Workspace UI (inherited); Enforced overrides: Organization
  • Review profile: ASSERTIVE
  • Plan: Enterprise
  • Run ID: 922a704d-5685-41d4-bdf1-ac812fdc4285

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@07souravkunda
07souravkunda marked this pull request as ready for review October 26, 2026 05:30
@07souravkunda
07souravkunda requested a review from a team as a code owner October 26, 2026 05:30
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