diff --git a/api_core/google/api_core/gapic_v1/routing_header.py b/api_core/google/api_core/gapic_v1/routing_header.py index ca3511611863..fc88bb6a6c2d 100644 --- a/api_core/google/api_core/gapic_v1/routing_header.py +++ b/api_core/google/api_core/gapic_v1/routing_header.py @@ -20,6 +20,8 @@ Generally, these headers are specified as gRPC metadata. """ +import sys + from six.moves.urllib.parse import urlencode ROUTING_METADATA_KEY = 'x-goog-request-params' @@ -35,7 +37,13 @@ def to_routing_header(params): Returns: str: The routing header string. """ - return urlencode(params) + if sys.version_info[0] < 3: + # Python 2 does not have the "safe" parameter for urlencode. + return urlencode(params).replace('%2F', '/') + return urlencode( + params, + # Per Google API policy (go/api-url-encoding), / is not encoded. + safe='/') def to_grpc_metadata(params): diff --git a/api_core/tests/unit/gapic/test_routing_header.py b/api_core/tests/unit/gapic/test_routing_header.py index d3a4bc35f7a2..6bedf292a0be 100644 --- a/api_core/tests/unit/gapic/test_routing_header.py +++ b/api_core/tests/unit/gapic/test_routing_header.py @@ -22,6 +22,12 @@ def test_to_routing_header(): assert value == "name=meep&book.read=1" +def test_to_routing_header_with_slashes(): + params = [('name', 'me/ep'), ('book.read', '1&2')] + value = routing_header.to_routing_header(params) + assert value == "name=me/ep&book.read=1%262" + + def test_to_grpc_metadata(): params = [('name', 'meep'), ('book.read', '1')] metadata = routing_header.to_grpc_metadata(params)