Skip to content

fix(abstractions): keep single value headers to one value when added as a string - #819

Merged
Vincent Biret (baywet) merged 2 commits into
microsoft:mainfrom
unknownhackerworld:fix/single-value-header-string
Oct 20, 2026
Merged

Vincent Biret (baywet) merged 2 commits into
microsoft:mainfrom
unknownhackerworld:fix/single-value-header-string

Conversation

@unknownhackerworld

@unknownhackerworld UNKNOWN H4CK3R (unknownhackerworld) commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Overview

HeadersCollection.add() now replaces the value of a single value header (content-type, content-encoding, content-length) when the value is passed as a string, the same way it already does when the value is passed as a list.

Before this change:

headers = HeadersCollection()
headers.add("Content-Type", "application/json")
headers.add("Content-Type", "text/plain")
headers.get("content-type")  # {'application/json', 'text/plain'}

After: {'text/plain'}.

Related Issue

Fixes #818

Notes

Root cause: in packages/abstractions/kiota_abstractions/headers_collection.py, add() has two branches. The list branch checks self.SINGLE_VALUE_HEADERS and replaces the set. The string branch skips that check and goes straight to values.add(header_values) on the existing set. add_all() calls add(key, value) with one string at a time, so merging collections hits the same branch.

Fix: wrap a string value in a one-item list at the top of add(), so both kinds of input go through one path that applies SINGLE_VALUE_HEADERS. The last value wins for single value headers. This matches kiota-dotnet's RequestHeaders.Add, which replaces single value headers no matter how many values are passed. It also removes the duplicated string branch, so add() is shorter than before.

Tests: test_add_single_value_header_to_existing_header used a subset check ({"value2"} <= headers.get("content-type")), so it passed while both values were kept. I changed it to an equality check, and added test_add_all_replaces_single_value_header for the add_all() path. Both fail on main and pass with this change.

Tradeoffs and alternatives:

  • try_add() is left as is. It already refuses to overwrite an existing header, which is its documented behavior.
  • I first added the SINGLE_VALUE_HEADERS check to the string branch as a one-line fix. That worked but pushed add() over SonarCloud's cognitive complexity limit (16 vs 15) and kept two copies of the same logic, so I normalized the input instead.
  • Behavior change: code that relied on add() keeping two Content-Type values would now see only the last one. The class name and existing test say single value headers should hold one value, so this looks like the intended behavior.

AI disclosure: this change was found and written with help from an AI coding assistant.

Testing Instructions

  • cd packages/abstractions && pip install -e . pytest pytest-asyncio
  • pytest tests/test_request_header.py: 13 passed (2 fail on main)
  • pytest tests: 158 passed
  • yapf --diff and mypy on kiota_abstractions/headers_collection.py are clean

Copilot AI balanced review requested due to automatic review settings October 20, 2026 11:32

This comment was marked as outdated.

@unknownhackerworld

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

…as a string

HeadersCollection.add() only applied SINGLE_VALUE_HEADERS in the list
branch. Adding a string value for content-type, content-encoding or
content-length appended it to the existing set, so the header ended up
with several values. add_all() goes through the same path.

Wrap a string value in a one-item list so both inputs share the list
path.

Fixes microsoft#818
Copilot AI balanced review requested due to automatic review settings October 20, 2026 11:41

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused fix preserves existing list and multi-value behavior, with regression coverage for both affected paths.

No open issues 🎉

Review effort: Balanced

@baywet Vincent Biret (baywet) left a comment

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.

Thanks for the contribution!

@github-project-automation github-project-automation Bot moved this to In Progress 🚧 in Kiota Oct 20, 2026
Copilot AI balanced review requested due to automatic review settings October 20, 2026 13:08

This comment was marked as off-topic.

@sonarqubecloud

Copy link
Copy Markdown

@baywet
Vincent Biret (baywet) merged commit bfa3c9b into microsoft:main Oct 20, 2026
63 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress 🚧 to Done ✔️ in Kiota Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done ✔️

Development

Successfully merging this pull request may close these issues.

HeadersCollection.add() keeps multiple values for single value headers when the value is a string

3 participants