From c8bbe18866ff1ae6c7ee9195cc2349764734c7f9 Mon Sep 17 00:00:00 2001 From: mukunda katta Date: Fri, 15 May 2026 13:05:49 -0700 Subject: [PATCH] fix: avoid duplicate interactions user-agent headers --- google/genai/_api_client.py | 22 +++++++++++++------ .../genai/tests/client/test_http_options.py | 20 ++++++++++++++++- google/genai/tests/interactions/test_auth.py | 11 ++++++++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/google/genai/_api_client.py b/google/genai/_api_client.py index e6202815e..a6523e921 100644 --- a/google/genai/_api_client.py +++ b/google/genai/_api_client.py @@ -123,15 +123,23 @@ def append_library_version_headers(headers: dict[str, str]) -> None: library_label = f'google-genai-sdk/{version.__version__}' language_label = 'gl-python/' + sys.version.split()[0] version_header_value = f'{library_label} {language_label}' + user_agent = None + for header_name in list(headers): + if header_name.lower() == 'user-agent': + value = headers.pop(header_name) + if user_agent is None or header_name == 'User-Agent': + user_agent = value if ( - 'user-agent' in headers - and library_label not in headers['user-agent'] + user_agent is not None + and library_label not in user_agent ): - headers['user-agent'] = f'{version_header_value} ' + headers['user-agent'] - elif 'user-agent' in headers and language_label not in headers['user-agent']: - headers['user-agent'] = f'{headers["user-agent"]} {language_label}' - elif 'user-agent' not in headers: - headers['user-agent'] = version_header_value + headers['User-Agent'] = f'{version_header_value} {user_agent}' + elif user_agent is not None and language_label not in user_agent: + headers['User-Agent'] = f'{user_agent} {language_label}' + elif user_agent is None: + headers['User-Agent'] = version_header_value + else: + headers['User-Agent'] = user_agent if ( 'x-goog-api-client' in headers and library_label not in headers['x-goog-api-client'] diff --git a/google/genai/tests/client/test_http_options.py b/google/genai/tests/client/test_http_options.py index e27808142..dba5bc22d 100644 --- a/google/genai/tests/client/test_http_options.py +++ b/google/genai/tests/client/test_http_options.py @@ -92,10 +92,28 @@ def test_patch_http_options_appends_version_headers(): timeout=10000, ) patched = _api_client.patch_http_options(original_options, patch_options) - assert 'user-agent' in patched.headers + assert 'User-Agent' in patched.headers assert 'x-goog-api-client' in patched.headers +def test_patch_http_options_canonicalizes_user_agent_header(): + original_options = types.HttpOptions( + headers={ + 'user-agent': 'lower-agent', + 'User-Agent': 'custom-agent', + } + ) + patched = _api_client.patch_http_options( + original_options, + types.HttpOptions(), + ) + + assert 'User-Agent' in patched.headers + assert 'user-agent' not in patched.headers + assert patched.headers['User-Agent'].endswith('custom-agent') + assert 'lower-agent' not in patched.headers['User-Agent'] + + def test_setting_timeout_populates_server_timeout_header(): api_client = _api_client.BaseApiClient( vertexai=False, diff --git a/google/genai/tests/interactions/test_auth.py b/google/genai/tests/interactions/test_auth.py index 5c92a225e..11f741e13 100644 --- a/google/genai/tests/interactions/test_auth.py +++ b/google/genai/tests/interactions/test_auth.py @@ -20,6 +20,7 @@ from ... import _base_url from unittest import mock import pytest +import httpx from httpx import Request, Response from ..._api_client import AsyncHttpxClient, BaseApiClient from httpx import Client as HTTPClient @@ -54,6 +55,16 @@ def test_interactions_gemini_url(monkeypatch): assert request.headers['x-goog-api-key'] == 'test-api-key' +def test_interactions_default_headers_have_single_user_agent(monkeypatch): + monkeypatch.setenv('GOOGLE_API_KEY', 'test-api-key') + client = Client() + + headers = httpx.Headers(client.aio.interactions._client.default_headers) + + assert len(headers.get_list('user-agent')) == 1 + assert 'google-genai-sdk/' in headers['user-agent'] + + def test_interactions_gemini_no_vertex_auth(monkeypatch): monkeypatch.setenv('GOOGLE_API_KEY', 'test-api-key') client = Client()