Merge User-Agent headers when cloning HTTP client#508
Merged
Conversation
These two markdown files are all a human needs to write — the e2e testing skill generates and manages the actual Playwright test code from here. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Instead of overwriting, clone() now concatenates User-Agent headers so each layer's identifier is preserved across nested clones. Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Claude <[email protected]>
lilyydu
previously approved these changes
Apr 10, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the shared HTTP Client.clone() behavior in @microsoft/teams.common to preserve layered identity by concatenating User-Agent values across nested clones, improving observability of which package/layer is issuing requests.
Changes:
- Concatenate parent + child
User-Agentvalues duringClient.clone()instead of overwriting. - Keep existing header spread semantics for non-
User-Agentheaders. - Add Jest coverage for 2-level and 3-level
User-Agentmerge scenarios and parent/child-only cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
packages/common/src/http/client.ts |
Implements User-Agent concatenation when cloning clients. |
packages/common/src/http/client.spec.ts |
Adds tests validating merged User-Agent behavior across clone levels. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
lilyydu
approved these changes
Apr 13, 2026
heyitsaamir
added a commit
to microsoft/teams.py
that referenced
this pull request
Apr 13, 2026
When `Client.clone()` was called with headers containing a `User-Agent`,
it would overwrite the base client's `User-Agent` rather than merging.
This loses the SDK's default UA token when callers supply their own.
## Changes
- **`packages/common/src/microsoft_teams/common/http/client.py`**
- Added `_merge_headers(base, overrides)` helper: performs a
case-insensitive `User-Agent` merge (space-concatenated, token-based
dedup to avoid substring false positives); all other headers follow
standard last-write-wins semantics
- `Client.clone()` now calls `_merge_headers()` instead of a plain dict
unpack
- **`packages/common/tests/test_client.py`**
- Added 7 tests covering: preservation without overrides, merge when
both sides define UA, non-UA overrides leave UA untouched,
case-insensitive key matching, duplicate-token suppression, substring
false-positive guard, and override-only UA when base has none
## Example
```python
client = Client(ClientOptions(headers={"User-Agent": "teams-py/1.0"}))
clone = client.clone(ClientOptions(headers={"User-Agent": "myapp/2.0"}))
# Before: "myapp/2.0" (SDK UA lost)
# After: "teams-py/1.0 myapp/2.0"
print(clone._options.headers["User-Agent"])
```
> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `releases.astral.sh`
> - Triggering command: `/home/REDACTED/.local/bin/uv uv sync
--all-packages --group dev` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/microsoft/teams.py/settings/copilot/coding_agent)
(admins only)
>
> </details>
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
> Implement the change described by PR microsoft/teams.ts#508 ("Merge
User-Agent headers when cloning HTTP client") in the Python SDK
repository @microsoft/teams.py.
>
> Goal:
> - When the HTTP client is cloned (or a new client is created from an
existing client/session), ensure that `User-Agent` headers are merged
rather than overwritten.
> - Preserve any existing default `User-Agent` set by the library while
also incorporating a user-provided `User-Agent` (or additional UA
tokens) when cloning.
>
> Requirements:
> 1. Locate the HTTP client implementation and any clone/copy method(s)
in the repository.
> 2. Identify how headers are stored (e.g., requests.Session headers,
httpx.Client headers, custom dict) and how cloning currently works.
> 3. Modify cloning logic so that:
> - If both source and override headers contain `User-Agent`, the
resulting `User-Agent` should include both (e.g., concatenated with a
space, or comma per convention) without duplicating identical values.
> - If only one side has `User-Agent`, keep it.
> - Header merging should be case-insensitive for the header key.
> 4. Add/adjust unit tests to cover:
> - Cloning without overrides preserves original `User-Agent`.
> - Cloning with headers override that includes `User-Agent` results in
merged value.
> - Cloning with headers override without `User-Agent` leaves original
UA intact.
> - Case-insensitive behavior (`user-agent`, `User-Agent`).
> 5. Update any relevant docs or changelog entry if the repo uses one.
>
> Reference:
> - PR: microsoft/teams.ts#508
>
> Notes:
> - Ensure behavior is consistent across sync/async HTTP clients if both
exist.
> - Keep backward compatibility with existing public APIs.
>
>
> The following is the prior conversation context from the user's chat
exploration (may be truncated):
>
> User: Can you implement this in @microsoft/teams.py ?
>
> Assistant: I’ve queued up the implementation for `microsoft/teams.py`
and I’m now waiting on your confirmation in the prompt to proceed with
making the code changes and opening the PR.
>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
*This pull request was created from Copilot chat.*
>
---------
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: heyitsaamir <[email protected]>
Co-authored-by: heyitsaamir <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Merged
heyitsaamir
added a commit
that referenced
this pull request
Apr 16, 2026
## Summary - Merges all changes from `main` since v2.0.7 into `release` - Sets `version.json` to stable `2.0.8` ### What's included - **feat:** Sovereign cloud support (GCCH, DoD, China) (#500) - **feat:** Add missing endpoints — Paged Members, Meeting Notifications & client gaps (#516) - **feat:** Graceful stream cancellation on 403 (#513) - **feat:** GitHub issue analysis → Teams notification workflow (#517) - **fix:** Improve error message when app credentials are missing (#527) - **fix:** Surface Graph API error body in GraphError (#524) - **fix:** Resolve missing deps, broken JSON, type errors, and typos in CLI templates (#521) - **fix:** Drain entire queue per flush cycle (#520) - **fix:** Merge User-Agent headers when cloning HTTP client (#508) - Dependency bumps: hono, axios, vite, @hono/node-server ## Post-merge 1. Trigger the [release pipeline](https://dev.azure.com/DomoreexpGithub/Github_Pipelines/_build?definitionId=52&_a=summary) for `release` with **Public** publish type 2. Bump `version.json` on `main` to `2.0.9-preview.{height}` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Client.clone()now concatenatesUser-Agentheaders instead of overwriting, so each layer's identifier is preserved (e.g.teams.ts[graph]/x.x teams.ts[apps]/x.x)Test plan
npx jest src/http/client.spec.tsfrompackages/common— all 23 tests pass