Skip to content

chore: Correct x-goog-api-client header logic #876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions firebase_admin/_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
DEFAULT_TIMEOUT_SECONDS = 120

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

class HttpClient:
Expand Down Expand Up @@ -76,7 +76,6 @@ def __init__(

if headers:
self._session.headers.update(headers)
self._session.headers.update(METRICS_HEADERS)
if retries:
self._session.mount('http://', requests.adapters.HTTPAdapter(max_retries=retries))
self._session.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries))
Expand Down Expand Up @@ -120,6 +119,7 @@ class call this method to send HTTP requests out. Refer to
"""
if 'timeout' not in kwargs:
kwargs['timeout'] = self.timeout
kwargs.setdefault('headers', {}).update(METRICS_HEADERS)
resp = self._session.request(method, self.base_url + url, **kwargs)
resp.raise_for_status()
return resp
Expand Down
2 changes: 1 addition & 1 deletion firebase_admin/app_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class _AppCheckService:
_jwks_client = None

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

def __init__(self, app):
Expand Down
2 changes: 1 addition & 1 deletion firebase_admin/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class _StorageClient:
"""Holds a Google Cloud Storage client instance."""

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

def __init__(self, credentials, project, default_bucket):
Expand Down
6 changes: 5 additions & 1 deletion tests/test_auth_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ def _assert_request(request, expected_method, expected_url):
assert request.method == expected_method
assert request.url == expected_url
assert request.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = [
_utils.get_metrics_header(),
_utils.get_metrics_header() + ' mock-cred-metric-tag'
]
assert request.headers['x-goog-api-client'] in expected_metrics_header

class TestOIDCProviderConfig:

Expand Down
6 changes: 4 additions & 2 deletions tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ def _assert_request(self, request, expected_method, expected_url):
assert request.url == expected_url
assert request.headers['Authorization'] == 'Bearer mock-token'
assert request.headers['User-Agent'] == db._USER_AGENT
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header

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

def test_get_value(self):
ref = db.reference('/test')
Expand Down
10 changes: 6 additions & 4 deletions tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ def test_task_enqueue(self):
assert recorder[0].url == _DEFAULT_REQUEST_URL
assert recorder[0].headers['Content-Type'] == 'application/json'
assert recorder[0].headers['Authorization'] == 'Bearer mock-token'
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header
assert task_id == 'test-task-id'

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

def test_task_delete(self):
Expand All @@ -149,8 +151,8 @@ def test_task_delete(self):
assert len(recorder) == 1
assert recorder[0].method == 'DELETE'
assert recorder[0].url == _DEFAULT_TASK_URL
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()

expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header

class TestTaskQueueOptions:

Expand Down
16 changes: 15 additions & 1 deletion tests/test_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,21 @@ def test_metrics_headers():
assert len(recorder) == 1
assert recorder[0].method == 'GET'
assert recorder[0].url == _TEST_URL
assert recorder[0].headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
assert recorder[0].headers['x-goog-api-client'] == _utils.get_metrics_header()

def test_metrics_headers_with_credentials():
client = _http_client.HttpClient(
credential=testutils.MockGoogleCredential())
assert client.session is not None
recorder = _instrument(client, 'body')
resp = client.request('get', _TEST_URL)
assert resp.status_code == 200
assert resp.text == 'body'
assert len(recorder) == 1
assert recorder[0].method == 'GET'
assert recorder[0].url == _TEST_URL
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert recorder[0].headers['x-goog-api-client'] == expected_metrics_header

def test_credential():
client = _http_client.HttpClient(
Expand Down
3 changes: 2 additions & 1 deletion tests/test_instance_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ def _instrument_iid_service(self, app, status=200, payload='True'):
def _assert_request(self, request, expected_method, expected_url):
assert request.method == expected_method
assert request.url == expected_url
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header

def _get_url(self, project_id, iid):
return instance_id._IID_SERVICE_URL + 'project/{0}/instanceId/{1}'.format(project_id, iid)
Expand Down
6 changes: 4 additions & 2 deletions tests/test_messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -1683,7 +1683,8 @@ def _assert_request(self, request, expected_method, expected_url, expected_body=
assert request.url == expected_url
assert request.headers['X-GOOG-API-FORMAT-VERSION'] == '2'
assert request.headers['X-FIREBASE-CLIENT'] == self._CLIENT_VERSION
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header
if expected_body is None:
assert request.body is None
else:
Expand Down Expand Up @@ -2604,7 +2605,8 @@ def _assert_request(self, request, expected_method, expected_url):
assert request.method == expected_method
assert request.url == expected_url
assert request.headers['access_token_auth'] == 'true'
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header

def _get_url(self, path):
return '{0}/{1}'.format(messaging._MessagingService.IID_URL, path)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_ml.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,8 @@ def _assert_request(request, expected_method, expected_url):
assert request.method == expected_method
assert request.url == expected_url
assert request.headers['X-FIREBASE-CLIENT'] == f'fire-admin-python/{firebase_admin.__version__}'
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header

class _TestStorageClient:
@staticmethod
Expand Down
3 changes: 2 additions & 1 deletion tests/test_project_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,8 @@ def _assert_request_is_correct(
assert request.method == expected_method
assert request.url == expected_url
assert request.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
assert request.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert request.headers['x-goog-api-client'] == expected_metrics_header
if expected_body is None:
assert request.body is None
else:
Expand Down
18 changes: 12 additions & 6 deletions tests/test_tenant_mgt.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ def test_get_tenant(self, tenant_mgt_app):
assert req.method == 'GET'
assert req.url == '{0}/tenants/tenant-id'.format(TENANT_MGT_URL_PREFIX)
assert req.headers['X-Client-Version'] == f'Python/Admin/{firebase_admin.__version__}'
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = _utils.get_metrics_header() + ' mock-cred-metric-tag'
assert req.headers['x-goog-api-client'] == expected_metrics_header

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

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

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

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

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

Expand Down
6 changes: 5 additions & 1 deletion tests/test_user_mgt.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ def _check_request(recorder, want_url, want_body=None, want_timeout=None):
req = recorder[0]
assert req.method == 'POST'
assert req.url == '{0}{1}'.format(USER_MGT_URLS['PREFIX'], want_url)
assert req.headers['X-GOOG-API-CLIENT'] == _utils.get_metrics_header()
expected_metrics_header = [
_utils.get_metrics_header(),
_utils.get_metrics_header() + ' mock-cred-metric-tag'
]
assert req.headers['x-goog-api-client'] in expected_metrics_header
if want_body:
body = json.loads(req.body.decode())
assert body == want_body
Expand Down
4 changes: 4 additions & 0 deletions tests/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ def refresh(self, request):
def service_account_email(self):
return 'mock-email'

# Simulate x-goog-api-client modification in credential refresh
def _metric_header_for_usage(self):
return 'mock-cred-metric-tag'


class MockCredential(firebase_admin.credentials.Base):
"""A mock Firebase credential implementation."""
Expand Down