Skip to content

Commit a384692

Browse files
committed
Add warning for users signing URLs without passing an explicit version.
1 parent 6c5cfc7 commit a384692

File tree

4 files changed

+82
-33
lines changed

4 files changed

+82
-33
lines changed

storage/google/cloud/storage/blob.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@
9797
_READ_LESS_THAN_SIZE = (
9898
"Size {:d} was specified but the file-like object only had " "{:d} bytes remaining."
9999
)
100+
_SIGNED_URL_V2_DEFAULT_MESSAGE = (
101+
"You have generated a signed URL using the default v2 signing "
102+
"implementation. In the future, this will default to v4. "
103+
"You may experience breaking changes if you use longer than 7 day "
104+
"expiration times with v4. To opt-in to the behavior specify version='v2'."
105+
)
100106

101107
_DEFAULT_CHUNKSIZE = 104857600 # 1024 * 1024 B * 100 = 100 MB
102108
_MAX_MULTIPART_SIZE = 8388608 # 8 MB
@@ -316,7 +322,7 @@ def generate_signed_url(
316322
query_parameters=None,
317323
client=None,
318324
credentials=None,
319-
version="v2",
325+
version=None,
320326
):
321327
"""Generates a signed URL for this blob.
322328
@@ -421,7 +427,10 @@ def generate_signed_url(
421427
:returns: A signed URL you can use to access the resource
422428
until expiration.
423429
"""
424-
if version not in ("v2", "v4"):
430+
if version is None:
431+
version = "v2"
432+
warnings.warn(DeprecationWarning(_SIGNED_URL_V2_DEFAULT_MESSAGE))
433+
elif version not in ("v2", "v4"):
425434
raise ValueError("'version' must be either 'v2' or 'v4'")
426435

427436
resource = "/{bucket_name}/{quoted_name}".format(

storage/google/cloud/storage/bucket.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
from google.cloud.storage._signing import generate_signed_url_v4
3838
from google.cloud.storage.acl import BucketACL
3939
from google.cloud.storage.acl import DefaultObjectACL
40+
from google.cloud.storage.blob import _SIGNED_URL_V2_DEFAULT_MESSAGE
4041
from google.cloud.storage.blob import Blob
4142
from google.cloud.storage.notification import BucketNotification
4243
from google.cloud.storage.notification import NONE_PAYLOAD_FORMAT
@@ -1983,7 +1984,7 @@ def generate_signed_url(
19831984
query_parameters=None,
19841985
client=None,
19851986
credentials=None,
1986-
version="v2",
1987+
version=None,
19871988
):
19881989
"""Generates a signed URL for this bucket.
19891990
@@ -2063,7 +2064,10 @@ def generate_signed_url(
20632064
:returns: A signed URL you can use to access the resource
20642065
until expiration.
20652066
"""
2066-
if version not in ("v2", "v4"):
2067+
if version is None:
2068+
version = "v2"
2069+
warnings.warn(DeprecationWarning(_SIGNED_URL_V2_DEFAULT_MESSAGE))
2070+
elif version not in ("v2", "v4"):
20672071
raise ValueError("'version' must be either 'v2' or 'v4'")
20682072

20692073
resource = "/{bucket_name}".format(bucket_name=self.name)

storage/tests/unit/test_blob.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import os
2121
import tempfile
2222
import unittest
23+
import warnings
2324

2425
import google.cloud.storage.blob
2526
import mock
@@ -363,7 +364,7 @@ def test_generate_signed_url_w_invalid_version(self):
363364

364365
def _generate_signed_url_helper(
365366
self,
366-
version,
367+
version=None,
367368
blob_name="blob-name",
368369
api_access_endpoint=None,
369370
method="GET",
@@ -393,24 +394,38 @@ def _generate_signed_url_helper(
393394
client = _Client(connection)
394395
bucket = _Bucket(client)
395396
blob = self._make_one(blob_name, bucket=bucket)
396-
to_patch = "google.cloud.storage.blob.generate_signed_url_{}".format(version)
397+
398+
if version is None:
399+
effective_version = "v2"
400+
else:
401+
effective_version = version
402+
403+
to_patch = "google.cloud.storage.blob.generate_signed_url_{}".format(
404+
effective_version)
397405

398406
with mock.patch(to_patch) as signer:
399-
signed_uri = blob.generate_signed_url(
400-
expiration=expiration,
401-
max_age=max_age,
402-
api_access_endpoint=api_access_endpoint,
403-
method=method,
404-
credentials=credentials,
405-
content_md5=content_md5,
406-
content_type=content_type,
407-
response_type=response_type,
408-
response_disposition=response_disposition,
409-
generation=generation,
410-
headers=headers,
411-
query_parameters=query_parameters,
412-
version=version,
413-
)
407+
with warnings.catch_warnings(record=True) as warned:
408+
signed_uri = blob.generate_signed_url(
409+
expiration=expiration,
410+
max_age=max_age,
411+
api_access_endpoint=api_access_endpoint,
412+
method=method,
413+
credentials=credentials,
414+
content_md5=content_md5,
415+
content_type=content_type,
416+
response_type=response_type,
417+
response_disposition=response_disposition,
418+
generation=generation,
419+
headers=headers,
420+
query_parameters=query_parameters,
421+
version=version,
422+
)
423+
424+
if version is None:
425+
self.assertEqual(len(warned), 1)
426+
self.assertIs(warned[0].category, DeprecationWarning)
427+
else:
428+
self.assertEqual(len(warned), 0)
414429

415430
self.assertEqual(signed_uri, signer.return_value)
416431

@@ -437,6 +452,9 @@ def _generate_signed_url_helper(
437452
}
438453
signer.assert_called_once_with(expected_creds, **expected_kwargs)
439454

455+
def test_generate_signed_url_no_version_passed_warning(self):
456+
self._generate_signed_url_helper()
457+
440458
def _generate_signed_url_v2_helper(self, **kw):
441459
version = "v2"
442460
self._generate_signed_url_helper(version, **kw)

storage/tests/unit/test_bucket.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import datetime
1616
import unittest
17+
import warnings
1718

1819
import mock
1920

@@ -2583,7 +2584,7 @@ def test_generate_signed_url_w_invalid_version(self):
25832584

25842585
def _generate_signed_url_helper(
25852586
self,
2586-
version,
2587+
version=None,
25872588
bucket_name="bucket-name",
25882589
api_access_endpoint=None,
25892590
method="GET",
@@ -2612,19 +2613,33 @@ def _generate_signed_url_helper(
26122613
connection = _Connection()
26132614
client = _Client(connection)
26142615
bucket = self._make_one(name=bucket_name, client=client)
2615-
to_patch = "google.cloud.storage.bucket.generate_signed_url_{}".format(version)
2616+
2617+
if version is None:
2618+
effective_version = "v2"
2619+
else:
2620+
effective_version = version
2621+
2622+
to_patch = "google.cloud.storage.bucket.generate_signed_url_{}".format(
2623+
effective_version)
26162624

26172625
with mock.patch(to_patch) as signer:
2618-
signed_uri = bucket.generate_signed_url(
2619-
expiration=expiration,
2620-
max_age=max_age,
2621-
api_access_endpoint=api_access_endpoint,
2622-
method=method,
2623-
credentials=credentials,
2624-
headers=headers,
2625-
query_parameters=query_parameters,
2626-
version=version,
2627-
)
2626+
with warnings.catch_warnings(record=True) as warned:
2627+
signed_uri = bucket.generate_signed_url(
2628+
expiration=expiration,
2629+
max_age=max_age,
2630+
api_access_endpoint=api_access_endpoint,
2631+
method=method,
2632+
credentials=credentials,
2633+
headers=headers,
2634+
query_parameters=query_parameters,
2635+
version=version,
2636+
)
2637+
2638+
if version is None:
2639+
self.assertEqual(len(warned), 1)
2640+
self.assertIs(warned[0].category, DeprecationWarning)
2641+
else:
2642+
self.assertEqual(len(warned), 0)
26282643

26292644
self.assertEqual(signed_uri, signer.return_value)
26302645

@@ -2646,6 +2661,9 @@ def _generate_signed_url_helper(
26462661
}
26472662
signer.assert_called_once_with(expected_creds, **expected_kwargs)
26482663

2664+
def test_generate_signed_url_no_version_passed_warning(self):
2665+
self._generate_signed_url_helper()
2666+
26492667
def _generate_signed_url_v2_helper(self, **kw):
26502668
version = "v2"
26512669
self._generate_signed_url_helper(version, **kw)

0 commit comments

Comments
 (0)