Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

Fix user agent string #398

Merged
merged 5 commits into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
62 changes: 62 additions & 0 deletions django_cloud_deploy/cloudlib/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2018 Google LLC
enriquejosepadilla marked this conversation as resolved.
Show resolved Hide resolved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper file for common functionality within cloublib."""


def set_user_agent(http, user_agent):
"""Set the user-agent on every request.

Args:
http - An instance of google_auth_httplib2.AuthorizedHttp.
enriquejosepadilla marked this conversation as resolved.
Show resolved Hide resolved
user_agent: string, the value for the user-agent header.

Returns:
A modified instance of http that was passed in.
enriquejosepadilla marked this conversation as resolved.
Show resolved Hide resolved

Example:

h = httplib2.Http()
h = set_user_agent(h, "my-app-name/6.0")

Most of the time the user-agent will be set doing auth, this is for the rare
cases where you are accessing an unauthenticated endpoint.
"""
request_orig = http.request
default_max_redirects = 5

# The closure that will replace 'httplib2.Http.request'.
def new_request(uri,
method='GET',
body=None,
headers=None,
redirections=default_max_redirects,
connection_type=None):
"""Modify the request headers to add the user-agent."""

if headers is None:
headers = {}
if 'user-agent' in headers:
headers['user-agent'] = user_agent + ' ' + headers['user-agent']
else:
headers['user-agent'] = user_agent
resp, content = request_orig(uri,
method,
body,
headers,
redirections=redirections,
connection_type=connection_type)
return resp, content

http.request = new_request
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait, why can't subclass here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

subclass google_auth_httplib2.AuthorizedHttp?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah. That seems like the obvious way to customize a classes behavior and I was wondering if that would be more appropriate here.

return http
10 changes: 5 additions & 5 deletions django_cloud_deploy/cloudlib/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
See https://gcloud-python.readthedocs.io/en/latest/resource-manager/api.html
"""

from django_cloud_deploy.cloudlib import _utils
from django_cloud_deploy import __version__
from typing import Any, Dict, List

import backoff
import google_auth_httplib2

from googleapiclient import discovery
from googleapiclient import http
from google.auth import credentials
from googleapiclient import errors

Expand Down Expand Up @@ -50,10 +51,9 @@ def __init__(self, cloudresourcemanager_service: discovery.Resource):

@classmethod
def from_credentials(cls, credentials: credentials.Credentials):
http_client = http.set_user_agent(http.build_http(),
'django-cloud-deploy')
auth_http = google_auth_httplib2.AuthorizedHttp(credentials,
http=http_client)
auth_http = google_auth_httplib2.AuthorizedHttp(credentials)
user_agent = '/'.join(['django-cloud-deploy', __version__.__version__])
auth_http = _utils.set_user_agent(auth_http, user_agent)
return cls(
discovery.build('cloudresourcemanager',
'v1',
Expand Down
42 changes: 42 additions & 0 deletions django_cloud_deploy/tests/unit/cloudlib/_utils_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for the cloudlib._utils module."""

from absl.testing import absltest

from django_cloud_deploy.cloudlib import _utils


class AuthorizedHttpFake(object):
"""Fakes the google_auth_httplib2.AuthorizedHttp Class"""

def request(self, uri, method='GET', body=None, headers=None, **kwargs):
"""Mock Implementation of httplib2's Http.request."""
user_agent = None
if headers:
user_agent = headers.get('user-agent')
return None, user_agent


class UtilsTestCase(absltest.TestCase):
"""Test case for Utils functions."""

def setUp(self):
self.mockHttp = AuthorizedHttpFake()

def test_set_user_agent(self):
user_agent = 'django-cloud-deploy/1.0'
self.assertIsNone(self.mockHttp.request(None)[1])
self.mockHttp = _utils.set_user_agent(self.mockHttp, user_agent)
self.assertEquals(user_agent, self.mockHttp.request(None)[1])