Skip to content

Commit 604d064

Browse files
authored
fix: pass headers as initial metadata to work around gRPC bug (grpc/grpc#22448) (#545)
MetadataInterceptor headers are silently dropped when gapic-common uses return_op: true. Return developer-token, login-customer-id, and linked-customer-id from ServiceLookup#headers as a workaround.
1 parent 110d6d3 commit 604d064

3 files changed

Lines changed: 66 additions & 2 deletions

File tree

lib/google/ads/google_ads/interceptors/metadata_interceptor.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def update_metadata(metadata)
6262
# Here we can directly access it.
6363
if metadata.key?(:"x-goog-api-client")
6464
if @ads_assistant
65-
metadata[:"x-goog-api-client"] += " gaada/#{@ads_assistant}"
65+
metadata[:"x-goog-api-client"] += " gaada/#{@ads_assistant}"
6666
end
6767

6868
# Check if "pb" is already in the header

lib/google/ads/google_ads/service_lookup.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,29 @@ def gax_service_params
7171
}
7272
end
7373

74+
# Workaround for gRPC Ruby bug (grpc/grpc#22448):
75+
# When gapic-common calls gRPC with `return_op: true`,
76+
# merge_metadata_to_send runs before interceptors execute,
77+
# so MetadataInterceptor's metadata changes are silently dropped.
78+
# Pass headers as initial metadata here until the upstream fix
79+
# (grpc/grpc#42073) is released.
7480
def headers
81+
h = {}
7582
if config.login_customer_id
7683
validate_customer_id(:login_customer_id)
84+
h[:"login-customer-id"] = config.login_customer_id.to_s
7785
end
7886

7987
if config.linked_customer_id
8088
validate_customer_id(:linked_customer_id)
89+
h[:"linked-customer-id"] = config.linked_customer_id.to_s
8190
end
8291

83-
{}
92+
unless config.use_cloud_org_for_api_access
93+
h[:"developer-token"] = config.developer_token if config.developer_token
94+
end
95+
96+
h
8497
end
8598

8699
def validate_customer_id(field)

test/test_service_lookup.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env ruby
2+
# Encoding: utf-8
3+
4+
require 'minitest/autorun'
5+
require 'google/ads/google_ads/service_lookup'
6+
require 'google/ads/google_ads/config'
7+
8+
class TestServiceLookup < Minitest::Test
9+
def create_lookup(config)
10+
Google::Ads::GoogleAds::ServiceLookup.new(
11+
nil, # lookup_util
12+
nil, # logger
13+
config,
14+
nil, # credentials_or_channel
15+
nil, # endpoint
16+
nil # deprecator
17+
)
18+
end
19+
20+
def test_headers_returns_empty_hash_when_nothing_set
21+
config = Google::Ads::GoogleAds::Config.new
22+
lookup = create_lookup(config)
23+
24+
assert_equal({}, lookup.send(:headers))
25+
end
26+
27+
def test_headers_includes_all_when_fully_configured
28+
config = Google::Ads::GoogleAds::Config.new do |c|
29+
c.login_customer_id = 1234567890
30+
c.linked_customer_id = 9876543210
31+
c.developer_token = "test-dev-token"
32+
end
33+
lookup = create_lookup(config)
34+
35+
headers = lookup.send(:headers)
36+
assert_equal "1234567890", headers[:"login-customer-id"]
37+
assert_equal "9876543210", headers[:"linked-customer-id"]
38+
assert_equal "test-dev-token", headers[:"developer-token"]
39+
end
40+
41+
def test_headers_excludes_developer_token_when_cloud_org
42+
config = Google::Ads::GoogleAds::Config.new do |c|
43+
c.developer_token = "test-dev-token"
44+
c.use_cloud_org_for_api_access = true
45+
end
46+
lookup = create_lookup(config)
47+
48+
headers = lookup.send(:headers)
49+
assert_nil headers[:"developer-token"]
50+
end
51+
end

0 commit comments

Comments
 (0)