Don't URL-encode slashes in gRPC request headers. (#6310)
Per internal document go/api-url-encoding (approved on 2017-04-20), "the
client library will %-encode everything except "/" and unreserved
characters, and the server will %-decode everything except "%2F"
and %2f"
This is currently affecting a private API which passes a resource name
(containing slashes) as a query parameter over gRPC.
diff --git a/google/api_core/gapic_v1/routing_header.py b/google/api_core/gapic_v1/routing_header.py
index ca35116..fc88bb6 100644
--- a/google/api_core/gapic_v1/routing_header.py
+++ b/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 @@
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/tests/unit/gapic/test_routing_header.py b/tests/unit/gapic/test_routing_header.py
index d3a4bc3..6bedf29 100644
--- a/tests/unit/gapic/test_routing_header.py
+++ b/tests/unit/gapic/test_routing_header.py
@@ -22,6 +22,12 @@
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)