Skip to content

Commit 70013c8

Browse files
authored
chore: Correct x-goog-api-client header logic (#876)
1 parent bde3fb0 commit 70013c8

14 files changed

+65
-24
lines changed

firebase_admin/_http_client.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
DEFAULT_TIMEOUT_SECONDS = 120
3939

4040
METRICS_HEADERS = {
41-
'X-GOOG-API-CLIENT': _utils.get_metrics_header(),
41+
'x-goog-api-client': _utils.get_metrics_header(),
4242
}
4343

4444
class HttpClient:
@@ -76,7 +76,6 @@ def __init__(
7676

7777
if headers:
7878
self._session.headers.update(headers)
79-
self._session.headers.update(METRICS_HEADERS)
8079
if retries:
8180
self._session.mount('http://', requests.adapters.HTTPAdapter(max_retries=retries))
8281
self._session.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries))
@@ -120,6 +119,7 @@ class call this method to send HTTP requests out. Refer to
120119
"""
121120
if 'timeout' not in kwargs:
122121
kwargs['timeout'] = self.timeout
122+
kwargs.setdefault('headers', {}).update(METRICS_HEADERS)
123123
resp = self._session.request(method, self.base_url + url, **kwargs)
124124
resp.raise_for_status()
125125
return resp

firebase_admin/app_check.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class _AppCheckService:
5252
_jwks_client = None
5353

5454
_APP_CHECK_HEADERS = {
55-
'X-GOOG-API-CLIENT': _utils.get_metrics_header(),
55+
'x-goog-api-client': _utils.get_metrics_header(),
5656
}
5757

5858
def __init__(self, app):

firebase_admin/storage.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class _StorageClient:
5656
"""Holds a Google Cloud Storage client instance."""
5757

5858
STORAGE_HEADERS = {
59-
'X-GOOG-API-CLIENT': _utils.get_metrics_header(),
59+
'x-goog-api-client': _utils.get_metrics_header(),
6060
}
6161

6262
def __init__(self, credentials, project, default_bucket):

tests/test_auth_providers.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ def _assert_request(request, expected_method, expected_url):
7575
assert request.method == expected_method
7676
assert request.url == expected_url
7777
assert request.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
78-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
78+
expected_metrics_header = [
79+
_utils.get_metrics_header(),
80+
_utils.get_metrics_header() + ' mock-cred-metric-tag'
81+
]
82+
assert request.headers['x-goog-api-client'] in expected_metrics_header
7983

8084
class TestOIDCProviderConfig:
8185

tests/test_db.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ def _assert_request(self, request, expected_method, expected_url):
198198
assert request.url == expected_url
199199
assert request.headers['Authorization'] == 'Bearer mock-token'
200200
assert request.headers['User-Agent'] == db._USER_AGENT
201-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
201+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
202+
assert request.headers['x-goog-api-client'] == expected_metrics_header
202203

203204
@pytest.mark.parametrize('data', valid_values)
204205
def test_get_value(self, data):
@@ -665,7 +666,8 @@ def _assert_request(self, request, expected_method, expected_url):
665666
assert request.url == expected_url
666667
assert request.headers['Authorization'] == 'Bearer mock-token'
667668
assert request.headers['User-Agent'] == db._USER_AGENT
668-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
669+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
670+
assert request.headers['x-goog-api-client'] == expected_metrics_header
669671

670672
def test_get_value(self):
671673
ref = db.reference('/test')

tests/test_functions.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def test_task_enqueue(self):
122122
assert recorder[0].url == _DEFAULT_REQUEST_URL
123123
assert recorder[0].headers['Content-Type'] == 'application/json'
124124
assert recorder[0].headers['Authorization'] == 'Bearer mock-token'
125-
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
125+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
126+
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header
126127
assert task_id == 'test-task-id'
127128

128129
def test_task_enqueue_with_extension(self):
@@ -139,7 +140,8 @@ def test_task_enqueue_with_extension(self):
139140
assert recorder[0].url == _CLOUD_TASKS_URL + resource_name
140141
assert recorder[0].headers['Content-Type'] == 'application/json'
141142
assert recorder[0].headers['Authorization'] == 'Bearer mock-token'
142-
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
143+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
144+
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header
143145
assert task_id == 'test-task-id'
144146

145147
def test_task_delete(self):
@@ -149,8 +151,8 @@ def test_task_delete(self):
149151
assert len(recorder) == 1
150152
assert recorder[0].method == 'DELETE'
151153
assert recorder[0].url == _DEFAULT_TASK_URL
152-
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
153-
154+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
155+
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header
154156

155157
class TestTaskQueueOptions:
156158

tests/test_http_client.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,21 @@ def test_metrics_headers():
7171
assert len(recorder) == 1
7272
assert recorder[0].method == 'GET'
7373
assert recorder[0].url == _TEST_URL
74-
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
74+
assert recorder[0].headers['x-goog-api-client'] == _utils.get_metrics_header()
75+
76+
def test_metrics_headers_with_credentials():
77+
client = _http_client.HttpClient(
78+
credential=testutils.MockGoogleCredential())
79+
assert client.session is not None
80+
recorder = _instrument(client, 'body')
81+
resp = client.request('get', _TEST_URL)
82+
assert resp.status_code == 200
83+
assert resp.text == 'body'
84+
assert len(recorder) == 1
85+
assert recorder[0].method == 'GET'
86+
assert recorder[0].url == _TEST_URL
87+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
88+
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header
7589

7690
def test_credential():
7791
client = _http_client.HttpClient(

tests/test_instance_id.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ def _instrument_iid_service(self, app, status=200, payload='True'):
6868
def _assert_request(self, request, expected_method, expected_url):
6969
assert request.method == expected_method
7070
assert request.url == expected_url
71-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
71+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
72+
assert request.headers['x-goog-api-client'] == expected_metrics_header
7273

7374
def _get_url(self, project_id, iid):
7475
return instance_id._IID_SERVICE_URL + 'project/{0}/instanceId/{1}'.format(project_id, iid)

tests/test_messaging.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1683,7 +1683,8 @@ def _assert_request(self, request, expected_method, expected_url, expected_body=
16831683
assert request.url == expected_url
16841684
assert request.headers['X-GOOG-API-FORMAT-VERSION'] == '2'
16851685
assert request.headers['X-FIREBASE-CLIENT'] == self._CLIENT_VERSION
1686-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
1686+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
1687+
assert request.headers['x-goog-api-client'] == expected_metrics_header
16871688
if expected_body is None:
16881689
assert request.body is None
16891690
else:
@@ -2604,7 +2605,8 @@ def _assert_request(self, request, expected_method, expected_url):
26042605
assert request.method == expected_method
26052606
assert request.url == expected_url
26062607
assert request.headers['access_token_auth'] == 'true'
2607-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
2608+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
2609+
assert request.headers['x-goog-api-client'] == expected_metrics_header
26082610

26092611
def _get_url(self, path):
26102612
return '{0}/{1}'.format(messaging._MessagingService.IID_URL, path)

tests/test_ml.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ def _assert_request(request, expected_method, expected_url):
339339
assert request.method == expected_method
340340
assert request.url == expected_url
341341
assert request.headers['X-FIREBASE-CLIENT'] == f'fire-admin-python/{firebase_admin.__version__}'
342-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
342+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
343+
assert request.headers['x-goog-api-client'] == expected_metrics_header
343344

344345
class _TestStorageClient:
345346
@staticmethod

tests/test_project_management.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,8 @@ def _assert_request_is_correct(
523523
assert request.method == expected_method
524524
assert request.url == expected_url
525525
assert request.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
526-
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
526+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
527+
assert request.headers['x-goog-api-client'] == expected_metrics_header
527528
if expected_body is None:
528529
assert request.body is None
529530
else:

tests/test_tenant_mgt.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ def test_get_tenant(self, tenant_mgt_app):
197197
assert req.method == 'GET'
198198
assert req.url == '{0}/tenants/tenant-id'.format(TENANT_MGT_URL_PREFIX)
199199
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
200-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
200+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
201+
assert req.headers['x-goog-api-client'] == expected_metrics_header
201202

202203
def test_tenant_not_found(self, tenant_mgt_app):
203204
_instrument_tenant_mgt(tenant_mgt_app, 500, TENANT_NOT_FOUND_RESPONSE)
@@ -289,7 +290,8 @@ def _assert_request(self, recorder, body):
289290
assert req.method == 'POST'
290291
assert req.url == '{0}/tenants'.format(TENANT_MGT_URL_PREFIX)
291292
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
292-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
293+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
294+
assert req.headers['x-goog-api-client'] == expected_metrics_header
293295
got = json.loads(req.body.decode())
294296
assert got == body
295297

@@ -389,7 +391,8 @@ def _assert_request(self, recorder, body, mask):
389391
assert req.url == '{0}/tenants/tenant-id?updateMask={1}'.format(
390392
TENANT_MGT_URL_PREFIX, ','.join(mask))
391393
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
392-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
394+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
395+
assert req.headers['x-goog-api-client'] == expected_metrics_header
393396
got = json.loads(req.body.decode())
394397
assert got == body
395398

@@ -411,7 +414,8 @@ def test_delete_tenant(self, tenant_mgt_app):
411414
assert req.method == 'DELETE'
412415
assert req.url == '{0}/tenants/tenant-id'.format(TENANT_MGT_URL_PREFIX)
413416
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
414-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
417+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
418+
assert req.headers['x-goog-api-client'] == expected_metrics_header
415419

416420
def test_tenant_not_found(self, tenant_mgt_app):
417421
_instrument_tenant_mgt(tenant_mgt_app, 500, TENANT_NOT_FOUND_RESPONSE)
@@ -555,7 +559,8 @@ def _assert_request(self, recorder, expected=None):
555559
req = recorder[0]
556560
assert req.method == 'GET'
557561
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
558-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
562+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
563+
assert req.headers['x-goog-api-client'] == expected_metrics_header
559564
request = dict(parse.parse_qsl(parse.urlsplit(req.url).query))
560565
assert request == expected
561566

@@ -932,7 +937,8 @@ def _assert_request(
932937
assert req.method == method
933938
assert req.url == '{0}/tenants/tenant-id{1}'.format(prefix, want_url)
934939
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
935-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
940+
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
941+
assert req.headers['x-goog-api-client'] == expected_metrics_header
936942
body = json.loads(req.body.decode())
937943
assert body == want_body
938944

tests/test_user_mgt.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ def _check_request(recorder, want_url, want_body=None, want_timeout=None):
136136
req = recorder[0]
137137
assert req.method == 'POST'
138138
assert req.url == '{0}{1}'.format(USER_MGT_URLS['PREFIX'], want_url)
139-
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
139+
expected_metrics_header = [
140+
_utils.get_metrics_header(),
141+
_utils.get_metrics_header() + ' mock-cred-metric-tag'
142+
]
143+
assert req.headers['x-goog-api-client'] in expected_metrics_header
140144
if want_body:
141145
body = json.loads(req.body.decode())
142146
assert body == want_body

tests/testutils.py

+4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ def refresh(self, request):
123123
def service_account_email(self):
124124
return 'mock-email'
125125

126+
# Simulate x-goog-api-client modification in credential refresh
127+
def _metric_header_for_usage(self):
128+
return 'mock-cred-metric-tag'
129+
126130

127131
class MockCredential(firebase_admin.credentials.Base):
128132
"""A mock Firebase credential implementation."""

0 commit comments

Comments
 (0)