Skip to content

Respect caller-provided User-Agent in Api.DownloadBytes#9458

Merged
Martin-Molinero merged 1 commit into
QuantConnect:masterfrom
AlexCatarino:bug-download-respect-user-agent-header
May 6, 2026
Merged

Respect caller-provided User-Agent in Api.DownloadBytes#9458
Martin-Molinero merged 1 commit into
QuantConnect:masterfrom
AlexCatarino:bug-download-respect-user-agent-header

Conversation

@AlexCatarino
Copy link
Copy Markdown
Member

Description

Api.DownloadBytes always set a default User-Agent header ("QCAlgorithm.Download(): User Agent Header") before applying caller-supplied headers. Because HttpRequestHeaders deduplicates case-insensitively but TryAddWithoutValidation does not replace an existing header, a caller that passed their own User-Agent (in any casing) ended up sending the default value instead of the one they specified.

The default is now applied only when the caller has not already supplied a User-Agent. The check uses DefaultRequestHeaders.Contains("User-Agent"), which matches header names case-insensitively per the HTTP spec, so user-agent, User-Agent, and USER-AGENT are all detected.

Related Issue

N/A — small fix surfaced while reviewing Api.DownloadBytes.

Motivation and Context

Algorithms calling QCAlgorithm.Download(...) with a custom User-Agent (e.g., to comply with a third-party API's UA policy) were silently overridden by the framework default, causing requests to be rejected or rate-limited by the remote endpoint.

Requires Documentation Change

No.

How Has This Been Tested?

  • Inspected HttpRequestHeaders.Contains semantics (case-insensitive header-name match).
  • Verified manually that:
    • When headers is null or has no UA, the default UA is added.
    • When headers contains a User-Agent (any casing), the default is skipped and the caller's value is sent.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

Skip setting the default "QCAlgorithm.Download(): User Agent Header"
when the caller already supplied a User-Agent in the headers dictionary.
The check uses HttpRequestHeaders.Contains, which matches header names
case-insensitively per the HTTP spec.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Martin-Molinero Martin-Molinero merged commit 2302a24 into QuantConnect:master May 6, 2026
7 of 8 checks passed
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.

3 participants