gapic-common 0.8.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b3ff94cc009d187db3bbcaa3268adc302baf7918c4027da5b6b7eeb35156f9b
4
- data.tar.gz: 48ffb516c68d49a72203f76f99e5bebd6cdd9760d96520f754cb6f51e9b39d52
3
+ metadata.gz: 2760df5ba60e10af0fcea12a09d984b020d5dde80a2969cef159272a1e766731
4
+ data.tar.gz: ad50bd4473dbf92bd8f31cdcaa0ab87bb08d53c359fc45f7b4f335bac0bcc56c
5
5
  SHA512:
6
- metadata.gz: f347fc6aae5fba58ab1fba7d090d34f116cbad71d02d8eaa7f7d6b498d830fb6fe0fdfc8fa80c2605a5077a194ee3b15c5ddb6d4d2be22f96f23c7e620afc36f
7
- data.tar.gz: dd712b166b3c4c2d5946fc4498fc36cc1758d236a987ff8f9efce7ccf8a8af75b07e447e35f29d98db7c00b42a2e67335ca84a9e55d29aa9606b48fb9a714f11
6
+ metadata.gz: ffd0f60edffb9a9d57113d13d46300d7da0102291d10977f5e900baf482a9c2822180a75460e0079e457dca861cd0bc9af15cc80694021de5c1ab9ad23b2c7a3
7
+ data.tar.gz: ed5d777bdb4ae4359b3fb6b1ee1b12e751541b565b08fdeacc4f698caeac878b7a3a540b2004bf63b7bb8a063da51620e7892ac5bcae98234ff969e804456cc7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Release History
2
2
 
3
+ ### 0.11.0 (2022-07-27)
4
+
5
+ #### Features
6
+
7
+ * Add CallOptions#merge and CallOptions equality checking ([#802](https://github.com/googleapis/gapic-generator-ruby/issues/802))
8
+
9
+ #### Bug Fixes
10
+
11
+ * transcoder should always preserve slashes ([#795](https://github.com/googleapis/gapic-generator-ruby/issues/795))
12
+
13
+ ### 0.10.0 (2022-06-20)
14
+
15
+ #### Features
16
+
17
+ * Require at least Ruby 2.6
18
+ * Support faraday 2.0
19
+ #### Bug Fixes
20
+
21
+ * Fix precision issues in protobuf timestamp conversion
22
+ * Fix some Ruby 3.0 keyword argument usage errors
23
+
24
+ ### 0.9.0 (2022-05-18)
25
+
26
+ #### Features
27
+
28
+ * add full grpc transcoding to gapic-common
29
+ #### Bug Fixes
30
+
31
+ * small fixes for combined libraries and testing
32
+
3
33
  ### 0.8.0 / 2022-01-20
4
34
 
5
35
  * Add generic LROs helpers. These are used for the Nonstandard (not conforming to AIP-151) Cloud LROs.
data/README.md CHANGED
@@ -15,11 +15,11 @@ convenient and idiomatic API surface to callers.
15
15
 
16
16
  ## Supported Ruby Versions
17
17
 
18
- This library is supported on Ruby 2.4+.
18
+ This library is supported on Ruby 2.6+.
19
19
 
20
20
  Google provides official support for Ruby versions that are actively supported
21
21
  by Ruby Core—that is, Ruby versions that are either in normal maintenance or in
22
- security maintenance, and not end of life. Currently, this means Ruby 2.4 and
22
+ security maintenance, and not end of life. Currently, this means Ruby 2.6 and
23
23
  later. Older versions of Ruby _may_ still work, but are unsupported and not
24
24
  recommended. See https://www.ruby-lang.org/en/downloads/branches/ for details
25
25
  about the Ruby support schedule.
@@ -28,7 +28,7 @@ about the Ruby support schedule.
28
28
 
29
29
  Contributions to this library are always welcome and highly encouraged.
30
30
 
31
- See the [CONTRIBUTING](CONTRIBUTING.md) documentation for more information on how to get started.
31
+ See the {file:CONTRIBUTING.md CONTRIBUTING} documentation for more information on how to get started.
32
32
 
33
33
  ## Versioning
34
34
 
@@ -74,6 +74,7 @@ module Gapic
74
74
  #
75
75
  # @param retry_policy [Hash] The policy for error retry. keys must match the arguments for
76
76
  # {RpcCall::RetryPolicy.new}.
77
+ #
77
78
  def apply_defaults retry_policy
78
79
  return unless retry_policy.is_a? Hash
79
80
 
@@ -85,6 +86,21 @@ module Gapic
85
86
  self
86
87
  end
87
88
 
89
+ # @private Equality test
90
+ def eql? other
91
+ other.is_a?(RetryPolicy) &&
92
+ other.retry_codes == retry_codes &&
93
+ other.initial_delay == initial_delay &&
94
+ other.multiplier == multiplier &&
95
+ other.max_delay == max_delay
96
+ end
97
+ alias == eql?
98
+
99
+ # @private Hash code
100
+ def hash
101
+ [retry_codes, initial_delay, multiplier, max_delay].hash
102
+ end
103
+
88
104
  # @private
89
105
  # See https://grpc.github.io/grpc/core/md_doc_statuscodes.html for a
90
106
  # list of error codes.
@@ -61,12 +61,18 @@ module Gapic
61
61
  # @param retry_policy [Hash] the policy for error retry.
62
62
  # @param retry_policy [Hash] The policy for error retry. keys must match the arguments for
63
63
  # {RetryPolicy.new}.
64
+ #
64
65
  def apply_defaults timeout: nil, metadata: nil, retry_policy: nil
65
66
  @timeout ||= timeout
66
67
  @metadata = metadata.merge @metadata if metadata
67
68
  @retry_policy.apply_defaults retry_policy if @retry_policy.respond_to? :apply_defaults
68
69
  end
69
70
 
71
+ ##
72
+ # Convert to hash form.
73
+ #
74
+ # @return [Hash]
75
+ #
70
76
  def to_h
71
77
  {
72
78
  timeout: timeout,
@@ -74,5 +80,31 @@ module Gapic
74
80
  retry_policy: retry_policy
75
81
  }
76
82
  end
83
+
84
+ ##
85
+ # Return a new CallOptions with the given modifications. The current object
86
+ # is not modified.
87
+ #
88
+ # @param kwargs [keywords] Updated fields. See {#initialize} for details.
89
+ # @return [CallOptions] A new CallOptions object.
90
+ #
91
+ def merge **kwargs
92
+ kwargs = to_h.merge kwargs
93
+ CallOptions.new(**kwargs)
94
+ end
95
+
96
+ # @private Equality test
97
+ def eql? other
98
+ other.is_a?(CallOptions) &&
99
+ other.timeout == timeout &&
100
+ other.metadata == metadata &&
101
+ other.retry_policy == retry_policy
102
+ end
103
+ alias == eql?
104
+
105
+ # @private Hash code
106
+ def hash
107
+ to_h.hash
108
+ end
77
109
  end
78
110
  end
@@ -0,0 +1,23 @@
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "json"
16
+
17
+ module Gapic
18
+ module Common
19
+ # Gapic Common exception class
20
+ class Error < StandardError
21
+ end
22
+ end
23
+ end
@@ -14,6 +14,6 @@
14
14
 
15
15
  module Gapic
16
16
  module Common
17
- VERSION = "0.8.0".freeze
17
+ VERSION = "0.11.0".freeze
18
18
  end
19
19
  end
data/lib/gapic/common.rb CHANGED
@@ -15,6 +15,7 @@
15
15
  require "grpc/errors"
16
16
  require "grpc/core/status_codes"
17
17
 
18
+ require "gapic/common/error"
18
19
  require "gapic/call_options"
19
20
  require "gapic/headers"
20
21
  require "gapic/operation"
@@ -198,7 +198,7 @@ module Gapic
198
198
  # @yield operation [Gapic::GenericLRO::Operation] Yields the finished Operation.
199
199
  #
200
200
  def wait_until_done! retry_policy: nil
201
- retry_policy = ::Gapic::Operation::RetryPolicy.new retry_policy if retry_policy.is_a? Hash
201
+ retry_policy = ::Gapic::Operation::RetryPolicy.new(**retry_policy) if retry_policy.is_a? Hash
202
202
  retry_policy ||= ::Gapic::Operation::RetryPolicy.new
203
203
 
204
204
  until done?
data/lib/gapic/headers.rb CHANGED
@@ -38,7 +38,7 @@ module Gapic
38
38
 
39
39
  ruby_version ||= ::RUBY_VERSION
40
40
  gax_version ||= ::Gapic::Common::VERSION
41
- grpc_version ||= ::GRPC::VERSION if defined? ::GRPC
41
+ grpc_version ||= ::GRPC::VERSION if defined? ::GRPC::VERSION
42
42
  rest_version ||= ::Faraday::VERSION if defined? ::Faraday
43
43
 
44
44
  x_goog_api_client_header = ["gl-ruby/#{ruby_version}"]
@@ -64,7 +64,7 @@ module Gapic
64
64
  #
65
65
  # # Or block until the operation completes, passing a block to be called
66
66
  # # on completion.
67
- # op.wait_until_done do |operation|
67
+ # op.wait_until_done! do |operation|
68
68
  # raise operation.results.message if operation.error?
69
69
  # # process(operation.results)
70
70
  # # process(operation.rmetadata)
@@ -253,7 +253,7 @@ module Gapic
253
253
  # @yield operation [Gapic::Operation] Yields the finished Operation.
254
254
  #
255
255
  def wait_until_done! retry_policy: nil
256
- retry_policy = RetryPolicy.new retry_policy if retry_policy.is_a? Hash
256
+ retry_policy = RetryPolicy.new(**retry_policy) if retry_policy.is_a? Hash
257
257
  retry_policy ||= RetryPolicy.new
258
258
 
259
259
  until done?
@@ -181,8 +181,7 @@ module Gapic
181
181
 
182
182
  min_repeated_field_number = fields.map(&:number).min
183
183
  if min_repeated_field_number != repeated_field.number
184
- raise ArgumentError, "#{@response.class} must have one primary repeated field " \
185
- "by both position and number"
184
+ raise ArgumentError, "#{@response.class} must have one primary repeated field by both position and number"
186
185
  end
187
186
 
188
187
  # We have the correct repeated field, save the field's name
@@ -134,7 +134,7 @@ module Gapic
134
134
  #
135
135
  # @return [Time] The converted Time.
136
136
  def self.timestamp_to_time timestamp
137
- Time.at timestamp.nanos * 10**-9 + timestamp.seconds
137
+ Time.at timestamp.seconds, timestamp.nanos, :nanosecond
138
138
  end
139
139
 
140
140
  ##
@@ -14,6 +14,7 @@
14
14
 
15
15
  require "googleauth"
16
16
  require "gapic/rest/faraday_middleware"
17
+ require "faraday/retry"
17
18
 
18
19
  module Gapic
19
20
  module Rest
@@ -37,13 +38,13 @@ module Gapic
37
38
  def initialize endpoint:, credentials:
38
39
  @endpoint = endpoint
39
40
  @endpoint = "https://#{endpoint}" unless /^https?:/.match? endpoint
40
- @endpoint.sub! %r{/$}, ""
41
+ @endpoint = @endpoint.sub %r{/$}, ""
41
42
 
42
43
  @credentials = credentials
43
44
 
44
45
  @connection = Faraday.new url: @endpoint do |conn|
45
46
  conn.headers = { "Content-Type" => "application/json" }
46
- conn.request :google_authorization, @credentials
47
+ conn.request :google_authorization, @credentials unless @credentials.is_a? ::Symbol
47
48
  conn.request :retry
48
49
  conn.response :raise_error
49
50
  conn.adapter :net_http
@@ -115,9 +116,8 @@ module Gapic
115
116
  make_http_request :put, uri: uri, body: body, params: params, options: options
116
117
  end
117
118
 
118
- protected
119
-
120
119
  ##
120
+ # @private
121
121
  # Sends a http request via Faraday
122
122
  # @param verb [Symbol] http verb
123
123
  # @param uri [String] uri to send this request to
@@ -13,11 +13,12 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require "json"
16
+ require "gapic/common/error"
16
17
 
17
18
  module Gapic
18
19
  module Rest
19
20
  # Gapic REST exception class
20
- class Error < StandardError
21
+ class Error < ::Gapic::Common::Error
21
22
  # @return [Integer] the http status code for the error
22
23
  attr_reader :status_code
23
24
 
@@ -0,0 +1,66 @@
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Gapic
16
+ module Rest
17
+ class GrpcTranscoder
18
+ # @private
19
+ # A single binding for GRPC-REST transcoding of a request
20
+ # It includes a uri template with bound field parameters, a HTTP method type,
21
+ # and a body template
22
+ #
23
+ # @attribute [r] method
24
+ # @return [Symbol] The REST verb for the request.
25
+ # @attribute [r] template
26
+ # @return [String] The URI template for the request.
27
+ # @attribute [r] field_bindings
28
+ # @return [Array<FieldBinding>] The field bindings for the URI template variables.
29
+ # @attribute [r] body
30
+ # @return [String] The body template for the request.
31
+ class HttpBinding
32
+ attr_reader :method
33
+ attr_reader :template
34
+ attr_reader :field_bindings
35
+ attr_reader :body
36
+
37
+ def initialize method, template, field_bindings, body
38
+ @method = method
39
+ @template = template
40
+ @field_bindings = field_bindings
41
+ @body = body
42
+ end
43
+
44
+ # A single binding for a field of a request message.
45
+ # @attribute [r] field_path
46
+ # @return [String] The path of the bound field, e.g. `foo.bar`.
47
+ # @attribute [r] regex
48
+ # @return [Regexp] The regex to match on the bound field's string representation.
49
+ # @attribute [r] preserve_slashes
50
+ # @return [Boolean] Whether the slashes in the field value should be preserved
51
+ # (as opposed to percent-escaped)
52
+ class FieldBinding
53
+ attr_reader :field_path
54
+ attr_reader :regex
55
+ attr_reader :preserve_slashes
56
+
57
+ def initialize field_path, regex, preserve_slashes
58
+ @field_path = field_path
59
+ @regex = regex
60
+ @preserve_slashes = preserve_slashes
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,294 @@
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "gapic/rest/grpc_transcoder/http_binding"
16
+
17
+ module Gapic
18
+ module Rest
19
+ # @private
20
+ # Transcodes a proto request message into HTTP Rest call components
21
+ # using a configuration of bindings.
22
+ # Internal doc go/actools-regapic-grpc-transcoding.
23
+ class GrpcTranscoder
24
+ def initialize bindings = nil
25
+ @bindings = bindings || []
26
+ end
27
+
28
+ ##
29
+ # @private
30
+ # Creates a new trascoder that is a copy of this one, but with an additional
31
+ # binding defined by the parameters.
32
+ #
33
+ # @param uri_method [Symbol] The rest verb for the binding.
34
+ # @param uri_template [String] The string with uri template for the binding.
35
+ # This string will be expanded with the parameters from variable bindings.
36
+ # @param matches [Array<Array>] Variable bindings in an array. Every element
37
+ # of the array is an [Array] triplet, where:
38
+ # - the first element is a [String] field path (e.g. `foo.bar`) in the request
39
+ # to bind to
40
+ # - the second element is a [Regexp] to match the field value
41
+ # - the third element is a [Boolean] whether the slashes in the field value
42
+ # should be preserved (as opposed to escaped) when expanding the uri template.
43
+ # @param body [String, Nil] The body template, e.g. `*` or a field path.
44
+ #
45
+ # @return [Gapic::Rest::GrpcTranscoder] The updated transcoder.
46
+ def with_bindings uri_method:, uri_template:, matches: [], body: nil
47
+ template = uri_template
48
+
49
+ matches.each do |name, _regex, _preserve_slashes|
50
+ unless uri_template =~ /({#{Regexp.quote name}})/
51
+ err_msg = "Binding configuration is incorrect: missing parameter in the URI template.\n" \
52
+ "Parameter `#{name}` is specified for matching but there is no corresponding parameter " \
53
+ "`{#{name}}` in the URI template."
54
+ raise ::Gapic::Common::Error, err_msg
55
+ end
56
+
57
+ template = template.gsub "{#{name}}", ""
58
+ end
59
+
60
+ if template =~ /{([a-zA-Z_.]+)}/
61
+ err_name = Regexp.last_match[1]
62
+ err_msg = "Binding configuration is incorrect: missing match configuration.\n" \
63
+ "Parameter `{#{err_name}}` is specified in the URI template but there is no " \
64
+ "corresponding match configuration for `#{err_name}`."
65
+ raise ::Gapic::Common::Error, err_msg
66
+ end
67
+
68
+ if body&.include? "."
69
+ raise ::Gapic::Common::Error,
70
+ "Provided body template `#{body}` points to a field in a sub-message. This is not supported."
71
+ end
72
+
73
+ field_bindings = matches.map do |name, regex, preserve_slashes|
74
+ HttpBinding::FieldBinding.new name, regex, preserve_slashes
75
+ end
76
+ GrpcTranscoder.new @bindings + [HttpBinding.new(uri_method, uri_template, field_bindings, body)]
77
+ end
78
+
79
+ ##
80
+ # @private
81
+ # Performs the full grpc transcoding -- creating a REST request from the GRPC request
82
+ # by matching the http bindings and choosing the last one to match.
83
+ # From the matching binding and the request the following components of the REST request
84
+ # are produced:
85
+ # - A [Symbol] representing the Rest verb (e.g. `:get`)
86
+ # - Uri [String] (e.g. `books/100:read`)
87
+ # - Query string params in the form of key-value pairs [Array<Array{String, String}>]
88
+ # (e.g. [["foo", "bar"], ["baz", "qux"]])
89
+ # - Body of the request [String]
90
+ #
91
+ # @param request [Object] The GRPC request object
92
+ #
93
+ # @return [Array] The components of the transcoded request.
94
+ def transcode request
95
+ # Using bindings in reverse here because of the "last one wins" rule
96
+ @bindings.reverse.each do |http_binding|
97
+ # The main reason we are using request.to_json here
98
+ # is that the unset proto3_optional fields will not be
99
+ # in that JSON, letting us skip the checks that would look like
100
+ # `request.respond_to?("has_#{key}?".to_sym) && !request.send("has_#{key}?".to_sym)`
101
+ # The reason we set emit_defaults: true is to avoid
102
+ # having to figure out default values for the required
103
+ # fields at a runtime.
104
+ #
105
+ # Make a new one for each binding because extract_scalar_value! is destructive
106
+ request_hash = JSON.parse request.to_json emit_defaults: true
107
+
108
+ uri_values = bind_uri_values! http_binding, request_hash
109
+ next if uri_values.any? { |_, value| value.nil? }
110
+
111
+ if http_binding.body && http_binding.body != "*"
112
+ # Note that the body template can only point to a top-level field,
113
+ # so there is no need to split the path.
114
+ body_binding_camel = camel_name_for http_binding.body
115
+ next unless request_hash.key? body_binding_camel
116
+ end
117
+
118
+ method = http_binding.method
119
+ uri = expand_template http_binding.template, uri_values
120
+ body, query_params = construct_body_query_params http_binding.body, request_hash, request
121
+
122
+ return method, uri, query_params, body
123
+ end
124
+
125
+ raise ::Gapic::Common::Error,
126
+ "Request object does not match any transcoding template. Cannot form a correct REST call."
127
+ end
128
+
129
+ private
130
+
131
+ # Binds request values for the uri template expansion.
132
+ # This method modifies the provided `request_hash` parameter.
133
+ # Returned values are percent-escaped with slashes potentially preserved.
134
+ # @param http_binding [Gapic::Rest::GrpcTranscoder::HttpBinding]
135
+ # Http binding to get the field bindings from.
136
+ # @param request_hash [Hash]
137
+ # A hash of the GRPC request with the unset proto3_optional fields pre-removed.
138
+ # !!! This hash will be modified. The bound fields will be deleted. !!!
139
+ # @return [Hash{String, String}]
140
+ # Name to value hash of the variables for the uri template expansion.
141
+ # The values are percent-escaped with slashes potentially preserved.
142
+ def bind_uri_values! http_binding, request_hash
143
+ http_binding.field_bindings.to_h do |field_binding|
144
+ field_path_camel = field_binding.field_path.split(".").map { |part| camel_name_for part }.join(".")
145
+ field_value = extract_scalar_value! request_hash, field_path_camel, field_binding.regex
146
+
147
+ if field_value
148
+ field_value = field_value.split("/").map { |segment| percent_escape(segment) }.join("/")
149
+ end
150
+
151
+ [field_binding.field_path, field_value]
152
+ end
153
+ end
154
+
155
+ # Percent-escapes a string.
156
+ # @param str [String] String to escape.
157
+ # @return str [String] Escaped string.
158
+ def percent_escape str
159
+ # `+` to represent spaces is not currently supported in Showcase server.
160
+ CGI.escape(str).gsub("+", "%20")
161
+ end
162
+
163
+ # Constructs body and query parameters for the Rest request.
164
+ # @param body_template [String, Nil] The template for the body, e.g. `*`.
165
+ # @param request_hash_without_uri [Hash]
166
+ # The hash of the GRPC request with the unset proto3_optional fields
167
+ # and the values that are bound to URI removed.
168
+ # @param request [Object] The GRPC request.
169
+ # @return [Array{String, Array}] A pair of body and query parameters.
170
+ def construct_body_query_params body_template, request_hash_without_uri, request
171
+ body = ""
172
+ query_params = []
173
+
174
+ if body_template == "*"
175
+ body = request_hash_without_uri.to_json
176
+ elsif body_template && body_template != ""
177
+ # Using a `request` here instead of `request_hash_without_uri`
178
+ # because if `body` is bound to a message field,
179
+ # the fields of the corresponding sub-message,
180
+ # which were used when constructing the URI, should not be deleted
181
+ # (as opposed to the case when `body` is `*`).
182
+ #
183
+ # The `request_hash_without_uri` at this point was mutated to delete these fields.
184
+ #
185
+ # Note that the body template can only point to a top-level field
186
+ request_hash_without_uri.delete camel_name_for body_template
187
+ body = request.send(body_template.to_sym).to_json(emit_defaults: true)
188
+ query_params = build_query_params request_hash_without_uri
189
+ else
190
+ query_params = build_query_params request_hash_without_uri
191
+ end
192
+
193
+ [body, query_params]
194
+ end
195
+
196
+ # Builds query params for the REST request.
197
+ # This function calls itself recursively for every submessage field, passing
198
+ # the submessage hash as request and the path to the submessage field as a prefix.
199
+ # @param request_hash [Hash]
200
+ # A hash of the GRPC request or the sub-request with the unset
201
+ # proto3_optional fields and the values that are bound to URI removed.
202
+ # @param prefix [String] A prefix to form the correct query parameter key.
203
+ # @return [Array{String, String}] Query string params as key-value pairs.
204
+ def build_query_params request_hash, prefix = ""
205
+ result = []
206
+ request_hash.each do |key, value|
207
+ full_key_name = "#{prefix}#{key}"
208
+ case value
209
+ when ::Array
210
+ value.each do |_val|
211
+ result.push "#{full_key_name}=#{value}"
212
+ end
213
+ when ::Hash
214
+ result += build_query_params value, "#{full_key_name}."
215
+ else
216
+ result.push "#{full_key_name}=#{value}" unless value.nil?
217
+ end
218
+ end
219
+
220
+ result
221
+ end
222
+
223
+ # Extracts a non-submessage non-array value from the request hash by path
224
+ # if its string representation matches the regex provided.
225
+ # This method modifies the provided `request_hash` parameter.
226
+ # Returns nil if:
227
+ # - the field is not found
228
+ # - the field is a Message or an array,
229
+ # - the regex does not match
230
+ # @param request_hash [Hash]
231
+ # A hash of the GRPC request or the sub-request with the unset
232
+ # proto3_optional fields removed.
233
+ # !!! This hash will be modified. The extracted field will be deleted. !!!
234
+ # @param field_path [String] A path to the field, e.g. `foo.bar`.
235
+ # @param regex [Regexp] A regex to match on the field's string representation.
236
+ # @return [String, Nil] the field's string representation or nil.
237
+ def extract_scalar_value! request_hash, field_path, regex
238
+ parent, name = find_value request_hash, field_path
239
+ value = parent.delete name
240
+
241
+ # Covers the case where in `foo.bar.baz`, `baz` is still a submessage or an array.
242
+ return nil if value.is_a?(::Hash) || value.is_a?(::Array)
243
+ return value.to_s if value.to_s =~ regex
244
+ end
245
+
246
+ # Finds a value in the hash by path.
247
+ # @param request_hash [Hash] A hash of the GRPC request or the sub-request.
248
+ # @param field_path [String] A path of the field, e.g. `foo.bar`.
249
+ def find_value request_hash, field_path
250
+ path_split = field_path.split "."
251
+
252
+ value_parent = nil
253
+ value = request_hash
254
+ last_field_name = nil
255
+ path_split.each do |curr_field|
256
+ # Covers the case when in `foo.bar.baz`, `bar` is not a submessage field
257
+ # or is a submessage field initialized with nil.
258
+ return {}, nil unless value.is_a? ::Hash
259
+ value_parent = value
260
+ last_field_name = curr_field
261
+ value = value[curr_field]
262
+ end
263
+
264
+ [value_parent, last_field_name]
265
+ end
266
+
267
+ # Performs variable expansion on the template using the bindings provided
268
+ # @param template [String] The Uri template.
269
+ # @param bindings [Hash{String, String}]
270
+ # The variable bindings. The values should be percent-escaped
271
+ # (with slashes potentially preserved).
272
+ # @return [String] The expanded template.
273
+ def expand_template template, bindings
274
+ result = template
275
+ bindings.each do |name, value|
276
+ result = result.gsub "{#{name}}", value
277
+ end
278
+ result
279
+ end
280
+
281
+ ##
282
+ # Converts a snake_case parameter name into camelCase for query string parameters.
283
+ # @param attr_name [String] Parameter name.
284
+ # @return [String] Camel-cased parameter name.
285
+ def camel_name_for attr_name
286
+ parts = attr_name.split "_"
287
+ first_part = parts[0]
288
+ other_parts = parts[1..]
289
+ other_parts_pascal = other_parts.map(&:capitalize).join
290
+ "#{first_part}#{other_parts_pascal}"
291
+ end
292
+ end
293
+ end
294
+ end
data/lib/gapic/rest.rb CHANGED
@@ -24,6 +24,7 @@ require "gapic/protobuf"
24
24
  require "gapic/rest/client_stub"
25
25
  require "gapic/rest/error"
26
26
  require "gapic/rest/faraday_middleware"
27
+ require "gapic/rest/grpc_transcoder"
27
28
  require "gapic/rest/operation"
28
29
  require "gapic/rest/paged_enumerable"
29
30
  require "json"
metadata CHANGED
@@ -1,56 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gapic-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google API Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-20 00:00:00.000000000 Z
11
+ date: 2022-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '1.3'
22
+ version: 3.a
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.9'
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: '1.3'
32
+ version: 3.a
27
33
  - !ruby/object:Gem::Dependency
28
- name: googleapis-common-protos
34
+ name: faraday-retry
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: 1.3.11
39
+ version: '1.0'
34
40
  - - "<"
35
41
  - !ruby/object:Gem::Version
36
- version: 2.a
42
+ version: 3.a
37
43
  type: :runtime
38
44
  prerelease: false
39
45
  version_requirements: !ruby/object:Gem::Requirement
40
46
  requirements:
41
47
  - - ">="
42
48
  - !ruby/object:Gem::Version
43
- version: 1.3.11
49
+ version: '1.0'
44
50
  - - "<"
45
51
  - !ruby/object:Gem::Version
46
- version: 2.a
52
+ version: 3.a
47
53
  - !ruby/object:Gem::Dependency
48
- name: googleapis-common-protos-types
54
+ name: googleapis-common-protos
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
57
  - - ">="
52
58
  - !ruby/object:Gem::Version
53
- version: 1.0.6
59
+ version: 1.3.12
54
60
  - - "<"
55
61
  - !ruby/object:Gem::Version
56
62
  version: 2.a
@@ -60,17 +66,17 @@ dependencies:
60
66
  requirements:
61
67
  - - ">="
62
68
  - !ruby/object:Gem::Version
63
- version: 1.0.6
69
+ version: 1.3.12
64
70
  - - "<"
65
71
  - !ruby/object:Gem::Version
66
72
  version: 2.a
67
73
  - !ruby/object:Gem::Dependency
68
- name: googleauth
74
+ name: googleapis-common-protos-types
69
75
  requirement: !ruby/object:Gem::Requirement
70
76
  requirements:
71
77
  - - ">="
72
78
  - !ruby/object:Gem::Version
73
- version: 0.17.0
79
+ version: 1.3.1
74
80
  - - "<"
75
81
  - !ruby/object:Gem::Version
76
82
  version: 2.a
@@ -80,10 +86,24 @@ dependencies:
80
86
  requirements:
81
87
  - - ">="
82
88
  - !ruby/object:Gem::Version
83
- version: 0.17.0
89
+ version: 1.3.1
84
90
  - - "<"
85
91
  - !ruby/object:Gem::Version
86
92
  version: 2.a
93
+ - !ruby/object:Gem::Dependency
94
+ name: googleauth
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '1.0'
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '1.0'
87
107
  - !ruby/object:Gem::Dependency
88
108
  name: google-protobuf
89
109
  requirement: !ruby/object:Gem::Requirement
@@ -132,28 +152,28 @@ dependencies:
132
152
  requirements:
133
153
  - - "~>"
134
154
  - !ruby/object:Gem::Version
135
- version: 1.25.1
155
+ version: 1.26.0
136
156
  type: :development
137
157
  prerelease: false
138
158
  version_requirements: !ruby/object:Gem::Requirement
139
159
  requirements:
140
160
  - - "~>"
141
161
  - !ruby/object:Gem::Version
142
- version: 1.25.1
162
+ version: 1.26.0
143
163
  - !ruby/object:Gem::Dependency
144
164
  name: minitest
145
165
  requirement: !ruby/object:Gem::Requirement
146
166
  requirements:
147
167
  - - "~>"
148
168
  - !ruby/object:Gem::Version
149
- version: '5.14'
169
+ version: '5.16'
150
170
  type: :development
151
171
  prerelease: false
152
172
  version_requirements: !ruby/object:Gem::Requirement
153
173
  requirements:
154
174
  - - "~>"
155
175
  - !ruby/object:Gem::Version
156
- version: '5.14'
176
+ version: '5.16'
157
177
  - !ruby/object:Gem::Dependency
158
178
  name: minitest-autotest
159
179
  requirement: !ruby/object:Gem::Requirement
@@ -270,6 +290,7 @@ files:
270
290
  - lib/gapic/call_options.rb
271
291
  - lib/gapic/call_options/retry_policy.rb
272
292
  - lib/gapic/common.rb
293
+ - lib/gapic/common/error.rb
273
294
  - lib/gapic/common/version.rb
274
295
  - lib/gapic/config.rb
275
296
  - lib/gapic/config/method.rb
@@ -288,6 +309,8 @@ files:
288
309
  - lib/gapic/rest/client_stub.rb
289
310
  - lib/gapic/rest/error.rb
290
311
  - lib/gapic/rest/faraday_middleware.rb
312
+ - lib/gapic/rest/grpc_transcoder.rb
313
+ - lib/gapic/rest/grpc_transcoder/http_binding.rb
291
314
  - lib/gapic/rest/operation.rb
292
315
  - lib/gapic/rest/paged_enumerable.rb
293
316
  - lib/gapic/stream_input.rb
@@ -303,14 +326,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
303
326
  requirements:
304
327
  - - ">="
305
328
  - !ruby/object:Gem::Version
306
- version: '2.5'
329
+ version: '2.6'
307
330
  required_rubygems_version: !ruby/object:Gem::Requirement
308
331
  requirements:
309
332
  - - ">="
310
333
  - !ruby/object:Gem::Version
311
334
  version: '0'
312
335
  requirements: []
313
- rubygems_version: 3.1.2
336
+ rubygems_version: 3.3.14
314
337
  signing_key:
315
338
  specification_version: 4
316
339
  summary: Common code for GAPIC-generated API clients