Skip to content

Commit 2e09755

Browse files
Update x-goog-api-client metadata header to use a interceptor.
This change introduces a MetadataInterceptor to handle the addition of developer-token, login-customer-id, linked-customer-id, and x-goog-api-client modification, similar to the Python implementation. The ServiceLookup and generated factories are updated to use this new interceptor. Also added a test for the new interceptor. Co-authored-by: dorasun <10905385+dorasun@users.noreply.github.com>
1 parent 439fd5d commit 2e09755

File tree

4 files changed

+173
-15
lines changed

4 files changed

+173
-15
lines changed

codegen/templates/services.rb.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module Google
99
def initialize(
1010
logging_interceptor:,
1111
error_interceptor:,
12+
metadata_interceptor:,
1213
credentials:,
1314
metadata:,
1415
endpoint:,
@@ -17,6 +18,7 @@ module Google
1718
@interceptors = [
1819
error_interceptor,
1920
logging_interceptor,
21+
metadata_interceptor
2022
].compact
2123
@credentials = credentials
2224
@metadata = metadata
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Encoding: utf-8
2+
#
3+
# Copyright 2022 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# Interceptor to add metadata headers to requests.
18+
19+
require 'grpc/generic/interceptors'
20+
require 'google/protobuf'
21+
22+
module Google
23+
module Ads
24+
module GoogleAds
25+
module Interceptors
26+
class MetadataInterceptor < GRPC::ClientInterceptor
27+
def initialize(developer_token, login_customer_id, linked_customer_id, use_cloud_org_for_api_access)
28+
super()
29+
@developer_token = developer_token
30+
@login_customer_id = login_customer_id
31+
@linked_customer_id = linked_customer_id
32+
@use_cloud_org_for_api_access = use_cloud_org_for_api_access
33+
end
34+
35+
def request_response(request:, call:, method:, metadata: {})
36+
update_metadata(metadata)
37+
yield
38+
end
39+
40+
def server_streamer(request:, call:, method:, metadata: {})
41+
update_metadata(metadata)
42+
yield
43+
end
44+
45+
private
46+
47+
def update_metadata(metadata)
48+
if !@use_cloud_org_for_api_access
49+
metadata[:"developer-token"] = @developer_token
50+
end
51+
52+
if @login_customer_id
53+
metadata[:"login-customer-id"] = @login_customer_id.to_s
54+
end
55+
56+
if @linked_customer_id
57+
metadata[:"linked-customer-id"] = @linked_customer_id.to_s
58+
end
59+
60+
# The python library iterates over metadata and modifies x-goog-api-client
61+
# Here we can directly access it.
62+
if metadata.key?(:"x-goog-api-client")
63+
# Check if "pb" is already in the header
64+
unless metadata[:"x-goog-api-client"].include?("pb")
65+
metadata[:"x-goog-api-client"] += " pb/#{Gem.loaded_specs["google-protobuf"].version}"
66+
end
67+
end
68+
end
69+
end
70+
end
71+
end
72+
end
73+
end

lib/google/ads/google_ads/service_lookup.rb

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
require 'google/ads/google_ads/interceptors/logging_interceptor'
22
require 'google/ads/google_ads/interceptors/error_interceptor'
3+
require 'google/ads/google_ads/interceptors/metadata_interceptor'
34

45
module Google
56
module Ads
@@ -26,27 +27,35 @@ def call
2627
logging_interceptor = GoogleAds::Interceptors::LoggingInterceptor.new(logger)
2728
end
2829
error_interceptor = GoogleAds::Interceptors::ErrorInterceptor.new
30+
metadata_interceptor = GoogleAds::Interceptors::MetadataInterceptor.new(
31+
config.developer_token,
32+
config.login_customer_id,
33+
config.linked_customer_id,
34+
config.use_cloud_org_for_api_access
35+
)
2936

3037
version_alternates = {}
3138
Factories::VERSIONS.each do |v|
32-
version_alternates[v] = factory_at_version(v, error_interceptor, logging_interceptor)
39+
version_alternates[v] = factory_at_version(v, error_interceptor, logging_interceptor, metadata_interceptor)
3340
end
3441

3542
highest_factory = factory_at_version(
3643
Factories::HIGHEST_VERSION,
3744
error_interceptor,
3845
logging_interceptor,
46+
metadata_interceptor,
3947
)
4048

4149
VersionAlternate.new(highest_factory, version_alternates)
4250
end
4351

4452
private
4553

46-
def factory_at_version(version, error_interceptor, logging_interceptor)
54+
def factory_at_version(version, error_interceptor, logging_interceptor, metadata_interceptor)
4755
factory = Factories.at_version(version).services.new(**{
4856
logging_interceptor: logging_interceptor,
4957
error_interceptor: error_interceptor,
58+
metadata_interceptor: metadata_interceptor,
5059
deprecation: deprecator
5160
}.merge(gax_service_params))
5261

@@ -62,27 +71,15 @@ def gax_service_params
6271
end
6372

6473
def headers
65-
headers = {}
66-
67-
# If config.use_cloud_org_for_api_access is not True, add the developer
68-
# token to the request's metadata
69-
if !config.use_cloud_org_for_api_access
70-
headers[:"developer-token"] = config.developer_token
71-
end
72-
7374
if config.login_customer_id
7475
validate_customer_id(:login_customer_id)
75-
# header values must be strings
76-
headers[:"login-customer-id"] = config.login_customer_id.to_s
7776
end
7877

7978
if config.linked_customer_id
8079
validate_customer_id(:linked_customer_id)
81-
# header values must be strings
82-
headers[:"linked-customer-id"] = config.linked_customer_id.to_s
8380
end
8481

85-
headers
82+
{}
8683
end
8784

8885
def validate_customer_id(field)

test/test_metadata_interceptor.rb

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env ruby
2+
# Encoding: utf-8
3+
4+
require 'minitest/autorun'
5+
require 'google/ads/google_ads/interceptors/metadata_interceptor'
6+
require 'google/protobuf'
7+
8+
class TestMetadataInterceptor < Minitest::Test
9+
attr_reader :mi
10+
11+
def setup
12+
@mi = Google::Ads::GoogleAds::Interceptors::MetadataInterceptor.new(
13+
"dev_token",
14+
"login_id",
15+
"linked_id",
16+
false
17+
)
18+
end
19+
20+
def test_adds_developer_token_if_not_cloud_org
21+
metadata = {}
22+
mi.request_response(
23+
request: nil,
24+
call: nil,
25+
method: nil,
26+
metadata: metadata
27+
) do
28+
end
29+
assert_equal "dev_token", metadata[:"developer-token"]
30+
end
31+
32+
def test_adds_login_and_linked_customer_id
33+
metadata = {}
34+
mi.request_response(
35+
request: nil,
36+
call: nil,
37+
method: nil,
38+
metadata: metadata
39+
) do
40+
end
41+
assert_equal "login_id", metadata[:"login-customer-id"]
42+
assert_equal "linked_id", metadata[:"linked-customer-id"]
43+
end
44+
45+
def test_appends_pb_version_to_x_goog_api_client
46+
metadata = { :"x-goog-api-client" => "gl-ruby/1.2.3" }
47+
mi.request_response(
48+
request: nil,
49+
call: nil,
50+
method: nil,
51+
metadata: metadata
52+
) do
53+
end
54+
assert_includes metadata[:"x-goog-api-client"], "pb/#{Gem.loaded_specs["google-protobuf"].version}"
55+
end
56+
57+
def test_does_not_duplicate_pb_version
58+
metadata = { :"x-goog-api-client" => "gl-ruby/1.2.3 pb/1.2.3" }
59+
mi.request_response(
60+
request: nil,
61+
call: nil,
62+
method: nil,
63+
metadata: metadata
64+
) do
65+
end
66+
assert_equal "gl-ruby/1.2.3 pb/1.2.3", metadata[:"x-goog-api-client"]
67+
end
68+
69+
def test_skips_developer_token_if_cloud_org
70+
mi_cloud = Google::Ads::GoogleAds::Interceptors::MetadataInterceptor.new(
71+
"dev_token",
72+
"login_id",
73+
"linked_id",
74+
true
75+
)
76+
metadata = {}
77+
mi_cloud.request_response(
78+
request: nil,
79+
call: nil,
80+
method: nil,
81+
metadata: metadata
82+
) do
83+
end
84+
assert_nil metadata[:"developer-token"]
85+
end
86+
end

0 commit comments

Comments
 (0)