gapic-common 0.11.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/lib/gapic/call_options/retry_policy.rb +1 -1
- data/lib/gapic/common/version.rb +1 -1
- data/lib/gapic/grpc/errors.rb +60 -0
- data/lib/gapic/grpc/service_stub/rpc_call.rb +17 -6
- data/lib/gapic/grpc/service_stub.rb +15 -15
- data/lib/gapic/grpc.rb +1 -0
- data/lib/gapic/headers.rb +5 -3
- data/lib/gapic/paged_enumerable.rb +3 -3
- data/lib/gapic/rest/client_stub.rb +27 -14
- data/lib/gapic/rest/error.rb +74 -11
- data/lib/gapic/rest/server_stream.rb +101 -0
- data/lib/gapic/rest/threaded_enumerator.rb +71 -0
- data/lib/gapic/rest.rb +2 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b5964ec91020c76501e2424be598b345a114a16515fe209135e46f552100d4e
|
4
|
+
data.tar.gz: 4a08e08fe15b6c6d6a3ad3097895a7d01bcfe3377f1392946a0cfe671ca97fdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0270a8d4933fda1f6297233f3465ae4fed20d34ebbf4bb766f228fe13746b5508c97179eb7c0b763d104c52079f59765b514c32a1d6cb2d61196791f007595a
|
7
|
+
data.tar.gz: 437633278a8640eee28a975c7821270b11c2127c72970e0259c29b5b643db37b8d394ac5ae1cd80cb367e10c1384311cc018e0a276804dfda7d8a91f9fffb13a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.13.0 (2022-10-26)
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* Implement server-side streaming support for REST calls in gapic-common ([#826](https://github.com/googleapis/gapic-generator-ruby/issues/826))
|
8
|
+
|
9
|
+
### 0.12.0 (2022-09-15)
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
* Support numeric_enums in the ClientStub ([#817](https://github.com/googleapis/gapic-generator-ruby/issues/817))
|
14
|
+
* parse details information from REST errors ([#815](https://github.com/googleapis/gapic-generator-ruby/issues/815))
|
15
|
+
* send protobuf version in headers ([#816](https://github.com/googleapis/gapic-generator-ruby/issues/816))
|
16
|
+
|
17
|
+
#### Bug Fixes
|
18
|
+
|
19
|
+
* rewrap certain grpc errors ([#810](https://github.com/googleapis/gapic-generator-ruby/issues/810))
|
20
|
+
This will rewrap some GRPC::Unavailable errors that were caused by authentication failing as Gapic::GRPC::AuthorizationError which inherits from ::GRPC::Unauthenticated
|
21
|
+
|
3
22
|
### 0.11.1 (2022-08-03)
|
4
23
|
|
5
24
|
#### Bug Fixes
|
data/lib/gapic/common/version.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright 2019 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 "googleauth"
|
16
|
+
require "gapic/common/error"
|
17
|
+
|
18
|
+
module Gapic
|
19
|
+
module GRPC
|
20
|
+
##
|
21
|
+
# An error class to represent the Authorization Error.
|
22
|
+
# The GRPC layer wraps auth plugin errors in ::GRPC::Unavailable.
|
23
|
+
# This class rewraps those GRPC layer errors, presenting a correct status code.
|
24
|
+
#
|
25
|
+
class AuthorizationError < ::GRPC::Unauthenticated
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# An error class that represents Deadline Exceeded error with an optional
|
30
|
+
# retry root cause.
|
31
|
+
#
|
32
|
+
# The GRPC layer throws ::GRPC::DeadlineExceeded without any context.
|
33
|
+
# If the deadline was exceeded while retrying another exception (e.g.
|
34
|
+
# ::GRPC::Unavailable), that exception could be useful for understanding
|
35
|
+
# the readon for the timeout.
|
36
|
+
#
|
37
|
+
# This exception rewraps ::GRPC::DeadlineExceeded, adding an exception
|
38
|
+
# that was being retried until the deadline was exceeded (if any) as a
|
39
|
+
# `root_cause` attribute.
|
40
|
+
#
|
41
|
+
# @!attribute [r] root_cause
|
42
|
+
# @return [Object, nil] The exception that was being retried
|
43
|
+
# when the DeadlineExceeded error occured.
|
44
|
+
#
|
45
|
+
class DeadlineExceededError < ::GRPC::DeadlineExceeded
|
46
|
+
attr_reader :root_cause
|
47
|
+
|
48
|
+
##
|
49
|
+
# @param message [String] The error message.
|
50
|
+
#
|
51
|
+
# @param root_cause [Object, nil] The exception that was being retried
|
52
|
+
# when the DeadlineExceeded error occured.
|
53
|
+
#
|
54
|
+
def initialize message, root_cause: nil
|
55
|
+
super message
|
56
|
+
@root_cause = root_cause
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
15
|
require "gapic/call_options"
|
16
|
+
require "grpc/errors"
|
16
17
|
|
17
18
|
module Gapic
|
18
19
|
class ServiceStub
|
@@ -45,7 +46,7 @@ module Gapic
|
|
45
46
|
#
|
46
47
|
# @yield [response, operation] Access the response along with the RPC operation.
|
47
48
|
# @yieldparam response [Object] The response object.
|
48
|
-
# @yieldparam operation [GRPC::ActiveCall::Operation] The RPC operation for the response.
|
49
|
+
# @yieldparam operation [::GRPC::ActiveCall::Operation] The RPC operation for the response.
|
49
50
|
#
|
50
51
|
# @return [Object] The response object.
|
51
52
|
#
|
@@ -55,7 +56,7 @@ module Gapic
|
|
55
56
|
# require "gapic"
|
56
57
|
# require "gapic/grpc"
|
57
58
|
#
|
58
|
-
# echo_channel = GRPC::Core::Channel.new(
|
59
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
59
60
|
# "localhost:7469", nil, :this_channel_is_insecure
|
60
61
|
# )
|
61
62
|
# echo_stub = Gapic::ServiceStub.new(
|
@@ -73,7 +74,7 @@ module Gapic
|
|
73
74
|
# require "gapic"
|
74
75
|
# require "gapic/grpc"
|
75
76
|
#
|
76
|
-
# echo_channel = GRPC::Core::Channel.new(
|
77
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
77
78
|
# "localhost:7469", nil, :this_channel_is_insecure
|
78
79
|
# )
|
79
80
|
# echo_stub = Gapic::ServiceStub.new(
|
@@ -85,7 +86,7 @@ module Gapic
|
|
85
86
|
# request = Google::Showcase::V1beta1::EchoRequest.new
|
86
87
|
# options = Gapic::CallOptions.new(
|
87
88
|
# retry_policy = {
|
88
|
-
# retry_codes: [GRPC::Core::StatusCodes::UNAVAILABLE]
|
89
|
+
# retry_codes: [::GRPC::Core::StatusCodes::UNAVAILABLE]
|
89
90
|
# }
|
90
91
|
# )
|
91
92
|
# response = echo_call.call request, options: options
|
@@ -96,7 +97,7 @@ module Gapic
|
|
96
97
|
# require "gapic"
|
97
98
|
# require "gapic/grpc"
|
98
99
|
#
|
99
|
-
# echo_channel = GRPC::Core::Channel.new(
|
100
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
100
101
|
# "localhost:7469", nil, :this_channel_is_insecure
|
101
102
|
# )
|
102
103
|
# echo_stub = Gapic::ServiceStub.new(
|
@@ -116,13 +117,23 @@ module Gapic
|
|
116
117
|
deadline = calculate_deadline options
|
117
118
|
metadata = options.metadata
|
118
119
|
|
120
|
+
retried_exception = nil
|
119
121
|
begin
|
120
122
|
operation = stub_method.call request, deadline: deadline, metadata: metadata, return_op: true
|
121
123
|
response = operation.execute
|
122
124
|
yield response, operation if block_given?
|
123
125
|
response
|
126
|
+
rescue ::GRPC::DeadlineExceeded => e
|
127
|
+
raise Gapic::GRPC::DeadlineExceededError.new e.message, root_cause: retried_exception
|
124
128
|
rescue StandardError => e
|
125
|
-
|
129
|
+
if e.is_a?(::GRPC::Unavailable) && /Signet::AuthorizationError/ =~ e.message
|
130
|
+
e = Gapic::GRPC::AuthorizationError.new e.message.gsub(%r{^\d+:}, "")
|
131
|
+
end
|
132
|
+
|
133
|
+
if check_retry?(deadline) && options.retry_policy.call(e)
|
134
|
+
retried_exception = e
|
135
|
+
retry
|
136
|
+
end
|
126
137
|
|
127
138
|
raise e
|
128
139
|
end
|
@@ -34,20 +34,20 @@ module Gapic
|
|
34
34
|
# @param grpc_stub_class [Class] gRPC stub class to create a new instance of.
|
35
35
|
# @param endpoint [String] The endpoint of the API.
|
36
36
|
# @param credentials [Google::Auth::Credentials, Signet::OAuth2::Client, String, Hash, Proc,
|
37
|
-
# GRPC::Core::Channel, GRPC::Core::ChannelCredentials] Provides the means for authenticating requests made by
|
37
|
+
# ::GRPC::Core::Channel, ::GRPC::Core::ChannelCredentials] Provides the means for authenticating requests made by
|
38
38
|
# the client. This parameter can be many types:
|
39
39
|
#
|
40
40
|
# * A `Google::Auth::Credentials` uses a the properties of its represented keyfile for authenticating requests
|
41
41
|
# made by this client.
|
42
42
|
# * A `Signet::OAuth2::Client` object used to apply the OAuth credentials.
|
43
|
-
# * A
|
44
|
-
# * A
|
45
|
-
# already be composed with a
|
43
|
+
# * A `::GRPC::Core::Channel` will be used to make calls through.
|
44
|
+
# * A `::GRPC::Core::ChannelCredentials` for the setting up the RPC client. The channel credentials should
|
45
|
+
# already be composed with a `::GRPC::Core::CallCredentials` object.
|
46
46
|
# * A `Proc` will be used as an updater_proc for the Grpc channel. The proc transforms the metadata for
|
47
47
|
# requests, generally, to give OAuth credentials.
|
48
48
|
# @param channel_args [Hash] The channel arguments. (This argument is ignored when `credentials` is
|
49
|
-
# provided as a
|
50
|
-
# @param interceptors [Array
|
49
|
+
# provided as a `::GRPC::Core::Channel`.)
|
50
|
+
# @param interceptors [Array<::GRPC::ClientInterceptor>] An array of {::GRPC::ClientInterceptor} objects that will
|
51
51
|
# be used for intercepting calls before they are executed Interceptors are an EXPERIMENTAL API.
|
52
52
|
#
|
53
53
|
def initialize grpc_stub_class, endpoint:, credentials:, channel_args: nil, interceptors: nil
|
@@ -59,10 +59,10 @@ module Gapic
|
|
59
59
|
interceptors = Array interceptors
|
60
60
|
|
61
61
|
@grpc_stub = case credentials
|
62
|
-
when GRPC::Core::Channel
|
62
|
+
when ::GRPC::Core::Channel
|
63
63
|
grpc_stub_class.new endpoint, nil, channel_override: credentials,
|
64
64
|
interceptors: interceptors
|
65
|
-
when GRPC::Core::ChannelCredentials, Symbol
|
65
|
+
when ::GRPC::Core::ChannelCredentials, Symbol
|
66
66
|
grpc_stub_class.new endpoint, credentials, channel_args: channel_args,
|
67
67
|
interceptors: interceptors
|
68
68
|
else
|
@@ -70,8 +70,8 @@ module Gapic
|
|
70
70
|
updater_proc ||= credentials if credentials.is_a? Proc
|
71
71
|
raise ArgumentError, "invalid credentials (#{credentials.class})" if updater_proc.nil?
|
72
72
|
|
73
|
-
call_creds = GRPC::Core::CallCredentials.new updater_proc
|
74
|
-
chan_creds = GRPC::Core::ChannelCredentials.new.compose call_creds
|
73
|
+
call_creds = ::GRPC::Core::CallCredentials.new updater_proc
|
74
|
+
chan_creds = ::GRPC::Core::ChannelCredentials.new.compose call_creds
|
75
75
|
grpc_stub_class.new endpoint, chan_creds, channel_args: channel_args,
|
76
76
|
interceptors: interceptors
|
77
77
|
end
|
@@ -88,7 +88,7 @@ module Gapic
|
|
88
88
|
#
|
89
89
|
# @yield [response, operation] Access the response along with the RPC operation.
|
90
90
|
# @yieldparam response [Object] The response object.
|
91
|
-
# @yieldparam operation [GRPC::ActiveCall::Operation] The RPC operation for the response.
|
91
|
+
# @yieldparam operation [::GRPC::ActiveCall::Operation] The RPC operation for the response.
|
92
92
|
#
|
93
93
|
# @return [Object] The response object.
|
94
94
|
#
|
@@ -98,7 +98,7 @@ module Gapic
|
|
98
98
|
# require "gapic"
|
99
99
|
# require "gapic/grpc"
|
100
100
|
#
|
101
|
-
# echo_channel = GRPC::Core::Channel.new(
|
101
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
102
102
|
# "localhost:7469", nil, :this_channel_is_insecure
|
103
103
|
# )
|
104
104
|
# echo_stub = Gapic::ServiceStub.new(
|
@@ -115,7 +115,7 @@ module Gapic
|
|
115
115
|
# require "gapic"
|
116
116
|
# require "gapic/grpc"
|
117
117
|
#
|
118
|
-
# echo_channel = GRPC::Core::Channel.new(
|
118
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
119
119
|
# "localhost:7469", nil, :this_channel_is_insecure
|
120
120
|
# )
|
121
121
|
# echo_stub = Gapic::ServiceStub.new(
|
@@ -126,7 +126,7 @@ module Gapic
|
|
126
126
|
# request = Google::Showcase::V1beta1::EchoRequest.new
|
127
127
|
# options = Gapic::CallOptions.new(
|
128
128
|
# retry_policy = {
|
129
|
-
# retry_codes: [GRPC::Core::StatusCodes::UNAVAILABLE]
|
129
|
+
# retry_codes: [::GRPC::Core::StatusCodes::UNAVAILABLE]
|
130
130
|
# }
|
131
131
|
# )
|
132
132
|
# response = echo_stub.call_rpc :echo, request
|
@@ -138,7 +138,7 @@ module Gapic
|
|
138
138
|
# require "gapic"
|
139
139
|
# require "gapic/grpc"
|
140
140
|
#
|
141
|
-
# echo_channel = GRPC::Core::Channel.new(
|
141
|
+
# echo_channel = ::GRPC::Core::Channel.new(
|
142
142
|
# "localhost:7469", nil, :this_channel_is_insecure
|
143
143
|
# )
|
144
144
|
# echo_stub = Gapic::ServiceStub.new(
|
data/lib/gapic/grpc.rb
CHANGED
data/lib/gapic/headers.rb
CHANGED
@@ -25,7 +25,7 @@ module Gapic
|
|
25
25
|
# @param lib_version [String] The client library version.
|
26
26
|
# @param gax_version [String] The Gapic version. Defaults to `Gapic::Common::VERSION`.
|
27
27
|
# @param gapic_version [String] The Gapic version.
|
28
|
-
# @param grpc_version [String] The GRPC version. Defaults to
|
28
|
+
# @param grpc_version [String] The GRPC version. Defaults to `::GRPC::VERSION`.
|
29
29
|
# @param rest_version [String] The Rest Library (Faraday) version. Defaults to `Faraday::VERSION`.
|
30
30
|
# @param transports_version_send [Array] Which transports to send versions for.
|
31
31
|
# Allowed values to contain are:
|
@@ -33,13 +33,14 @@ module Gapic
|
|
33
33
|
# `:rest` to send the REST library version (if defined)
|
34
34
|
# Defaults to `[:grpc]`
|
35
35
|
def self.x_goog_api_client ruby_version: nil, lib_name: nil, lib_version: nil, gax_version: nil,
|
36
|
-
gapic_version: nil, grpc_version: nil, rest_version: nil,
|
36
|
+
gapic_version: nil, grpc_version: nil, rest_version: nil, protobuf_version: nil,
|
37
37
|
transports_version_send: [:grpc]
|
38
38
|
|
39
39
|
ruby_version ||= ::RUBY_VERSION
|
40
40
|
gax_version ||= ::Gapic::Common::VERSION
|
41
41
|
grpc_version ||= ::GRPC::VERSION if defined? ::GRPC::VERSION
|
42
|
-
rest_version ||= ::Faraday::VERSION if defined? ::Faraday
|
42
|
+
rest_version ||= ::Faraday::VERSION if defined? ::Faraday::VERSION
|
43
|
+
protobuf_version ||= Gem.loaded_specs["google-protobuf"].version.to_s if Gem.loaded_specs.key? "google-protobuf"
|
43
44
|
|
44
45
|
x_goog_api_client_header = ["gl-ruby/#{ruby_version}"]
|
45
46
|
x_goog_api_client_header << "#{lib_name}/#{lib_version}" if lib_name
|
@@ -47,6 +48,7 @@ module Gapic
|
|
47
48
|
x_goog_api_client_header << "gapic/#{gapic_version}" if gapic_version
|
48
49
|
x_goog_api_client_header << "grpc/#{grpc_version}" if grpc_version && transports_version_send.include?(:grpc)
|
49
50
|
x_goog_api_client_header << "rest/#{rest_version}" if rest_version && transports_version_send.include?(:rest)
|
51
|
+
x_goog_api_client_header << "pb/#{protobuf_version}" if protobuf_version
|
50
52
|
x_goog_api_client_header.join " ".freeze
|
51
53
|
end
|
52
54
|
end
|
@@ -53,7 +53,7 @@ module Gapic
|
|
53
53
|
# @param method_name [Symbol] The RPC method name.
|
54
54
|
# @param request [Object] The request object.
|
55
55
|
# @param response [Object] The response object.
|
56
|
-
# @param operation [GRPC::ActiveCall::Operation] The RPC operation for the response.
|
56
|
+
# @param operation [::GRPC::ActiveCall::Operation] The RPC operation for the response.
|
57
57
|
# @param options [Gapic::CallOptions] The options for making the RPC call.
|
58
58
|
# @param format_resource [Proc] A Proc object to format the resource object. The Proc should accept response as an
|
59
59
|
# argument, and return a formatted resource object. Optional.
|
@@ -195,7 +195,7 @@ module Gapic
|
|
195
195
|
# @attribute [r] response
|
196
196
|
# @return [Object] the response object for the page.
|
197
197
|
# @attribute [r] operation
|
198
|
-
# @return [GRPC::ActiveCall::Operation] the RPC operation for the page.
|
198
|
+
# @return [::GRPC::ActiveCall::Operation] the RPC operation for the page.
|
199
199
|
class Page
|
200
200
|
include Enumerable
|
201
201
|
attr_reader :response
|
@@ -205,7 +205,7 @@ module Gapic
|
|
205
205
|
# @private
|
206
206
|
# @param response [Object] The response object for the page.
|
207
207
|
# @param resource_field [String] The name of the field in response which holds the resources.
|
208
|
-
# @param operation [GRPC::ActiveCall::Operation] the RPC operation for the page.
|
208
|
+
# @param operation [::GRPC::ActiveCall::Operation] the RPC operation for the page.
|
209
209
|
# @param format_resource [Proc] A Proc object to format the resource object. The Proc should accept response as an
|
210
210
|
# argument, and return a formatted resource object. Optional.
|
211
211
|
#
|
@@ -32,15 +32,17 @@ module Gapic
|
|
32
32
|
# @param credentials [Google::Auth::Credentials]
|
33
33
|
# Credentials to send with calls in form of a googleauth credentials object.
|
34
34
|
# (see the [googleauth docs](https://googleapis.dev/ruby/googleauth/latest/index.html))
|
35
|
+
# @param numeric_enums [Boolean] Whether to signal the server to JSON-encode enums as ints
|
35
36
|
#
|
36
37
|
# @yield [Faraday::Connection]
|
37
38
|
#
|
38
|
-
def initialize endpoint:, credentials:
|
39
|
+
def initialize endpoint:, credentials:, numeric_enums: false
|
39
40
|
@endpoint = endpoint
|
40
41
|
@endpoint = "https://#{endpoint}" unless /^https?:/.match? endpoint
|
41
42
|
@endpoint = @endpoint.sub %r{/$}, ""
|
42
43
|
|
43
44
|
@credentials = credentials
|
45
|
+
@numeric_enums = numeric_enums
|
44
46
|
|
45
47
|
@connection = Faraday.new url: @endpoint do |conn|
|
46
48
|
conn.headers = { "Content-Type" => "application/json" }
|
@@ -58,8 +60,8 @@ module Gapic
|
|
58
60
|
#
|
59
61
|
# @param uri [String] uri to send this request to
|
60
62
|
# @param params [Hash] query string parameters for the request
|
61
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
62
|
-
#
|
63
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
64
|
+
# to the REST call. Currently only timeout and headers are supported.
|
63
65
|
# @return [Faraday::Response]
|
64
66
|
def make_get_request uri:, params: {}, options: {}
|
65
67
|
make_http_request :get, uri: uri, body: nil, params: params, options: options
|
@@ -70,8 +72,8 @@ module Gapic
|
|
70
72
|
#
|
71
73
|
# @param uri [String] uri to send this request to
|
72
74
|
# @param params [Hash] query string parameters for the request
|
73
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
74
|
-
#
|
75
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
76
|
+
# to the REST call. Currently only timeout and headers are supported.
|
75
77
|
# @return [Faraday::Response]
|
76
78
|
def make_delete_request uri:, params: {}, options: {}
|
77
79
|
make_http_request :delete, uri: uri, body: nil, params: params, options: options
|
@@ -83,8 +85,8 @@ module Gapic
|
|
83
85
|
# @param uri [String] uri to send this request to
|
84
86
|
# @param body [String] a body to send with the request, nil for requests without a body
|
85
87
|
# @param params [Hash] query string parameters for the request
|
86
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
87
|
-
#
|
88
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
89
|
+
# to the REST call. Currently only timeout and headers are supported.
|
88
90
|
# @return [Faraday::Response]
|
89
91
|
def make_patch_request uri:, body:, params: {}, options: {}
|
90
92
|
make_http_request :patch, uri: uri, body: body, params: params, options: options
|
@@ -96,8 +98,8 @@ module Gapic
|
|
96
98
|
# @param uri [String] uri to send this request to
|
97
99
|
# @param body [String] a body to send with the request, nil for requests without a body
|
98
100
|
# @param params [Hash] query string parameters for the request
|
99
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
100
|
-
#
|
101
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
102
|
+
# to the REST call. Currently only timeout and headers are supported.
|
101
103
|
# @return [Faraday::Response]
|
102
104
|
def make_post_request uri:, body: nil, params: {}, options: {}
|
103
105
|
make_http_request :post, uri: uri, body: body, params: params, options: options
|
@@ -109,8 +111,8 @@ module Gapic
|
|
109
111
|
# @param uri [String] uri to send this request to
|
110
112
|
# @param body [String] a body to send with the request, nil for requests without a body
|
111
113
|
# @param params [Hash] query string parameters for the request
|
112
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
113
|
-
#
|
114
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
115
|
+
# to the REST call. Currently only timeout and headers are supported.
|
114
116
|
# @return [Faraday::Response]
|
115
117
|
def make_put_request uri:, body: nil, params: {}, options: {}
|
116
118
|
make_http_request :put, uri: uri, body: body, params: params, options: options
|
@@ -123,15 +125,26 @@ module Gapic
|
|
123
125
|
# @param uri [String] uri to send this request to
|
124
126
|
# @param body [String, nil] a body to send with the request, nil for requests without a body
|
125
127
|
# @param params [Hash] query string parameters for the request
|
126
|
-
# @param options [::Gapic::CallOptions] gapic options to be applied
|
127
|
-
#
|
128
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
129
|
+
# to the REST call. Currently only timeout and headers are supported.
|
130
|
+
# @param is_server_streaming [Boolean] flag if method is streaming
|
131
|
+
# @yieldparam chunk [String] The chunk of data received during server streaming.
|
128
132
|
# @return [Faraday::Response]
|
129
|
-
def make_http_request verb, uri:, body:, params:, options:
|
133
|
+
def make_http_request verb, uri:, body:, params:, options:, is_server_streaming: false
|
134
|
+
if @numeric_enums && (!params.key?("$alt") || params["$alt"] == "json")
|
135
|
+
params = params.merge({ "$alt" => "json;enum-encoding=int" })
|
136
|
+
end
|
137
|
+
options = ::Gapic::CallOptions.new(**options.to_h) unless options.is_a? ::Gapic::CallOptions
|
130
138
|
@connection.send verb, uri do |req|
|
131
139
|
req.params = params if params.any?
|
132
140
|
req.body = body unless body.nil?
|
133
141
|
req.headers = req.headers.merge options.metadata
|
134
142
|
req.options.timeout = options.timeout if options.timeout&.positive?
|
143
|
+
if is_server_streaming
|
144
|
+
req.options.on_data = proc do |chunk, _overall_received_bytes|
|
145
|
+
yield chunk
|
146
|
+
end
|
147
|
+
end
|
135
148
|
end
|
136
149
|
end
|
137
150
|
end
|
data/lib/gapic/rest/error.rb
CHANGED
@@ -19,16 +19,30 @@ module Gapic
|
|
19
19
|
module Rest
|
20
20
|
# Gapic REST exception class
|
21
21
|
class Error < ::Gapic::Common::Error
|
22
|
-
# @return [Integer] the http status code for the error
|
22
|
+
# @return [Integer, nil] the http status code for the error
|
23
23
|
attr_reader :status_code
|
24
|
+
# @return [Object, nil] the text representation of status as parsed from the response body
|
25
|
+
attr_reader :status
|
26
|
+
# @return [Object, nil] the details as parsed from the response body
|
27
|
+
attr_reader :details
|
28
|
+
# @return [Object, nil] the headers of the REST error
|
29
|
+
attr_reader :headers
|
30
|
+
# The Cloud error wrapper expect to see a `header` property
|
31
|
+
alias header headers
|
24
32
|
|
25
33
|
##
|
26
34
|
# @param message [String, nil] error message
|
27
35
|
# @param status_code [Integer, nil] HTTP status code of this error
|
36
|
+
# @param status [String, nil] The text representation of status as parsed from the response body
|
37
|
+
# @param details [Object, nil] Details data of this error
|
38
|
+
# @param headers [Object, nil] Http headers data of this error
|
28
39
|
#
|
29
|
-
def initialize message, status_code
|
30
|
-
@status_code = status_code
|
40
|
+
def initialize message, status_code, status: nil, details: nil, headers: nil
|
31
41
|
super message
|
42
|
+
@status_code = status_code
|
43
|
+
@status = status
|
44
|
+
@details = details
|
45
|
+
@headers = headers
|
32
46
|
end
|
33
47
|
|
34
48
|
class << self
|
@@ -37,36 +51,85 @@ module Gapic
|
|
37
51
|
# it tries to parse and set a detailed message and an error code from
|
38
52
|
# from the Google Cloud's response body
|
39
53
|
#
|
54
|
+
# @param err [Faraday::Error] the Faraday error to wrap
|
55
|
+
#
|
56
|
+
# @return [ Gapic::Rest::Error]
|
40
57
|
def wrap_faraday_error err
|
41
58
|
message = err.message
|
42
59
|
status_code = err.response_status
|
60
|
+
status = nil
|
61
|
+
details = nil
|
62
|
+
headers = err.response_headers
|
43
63
|
|
44
64
|
if err.response_body
|
45
|
-
msg, code = try_parse_from_body err.response_body
|
65
|
+
msg, code, status, details = try_parse_from_body err.response_body
|
46
66
|
message = "An error has occurred when making a REST request: #{msg}" unless msg.nil?
|
47
67
|
status_code = code unless code.nil?
|
48
68
|
end
|
49
69
|
|
50
|
-
Gapic::Rest::Error.new message, status_code
|
70
|
+
Gapic::Rest::Error.new message, status_code, status: status, details: details, headers: headers
|
51
71
|
end
|
52
72
|
|
53
73
|
private
|
54
74
|
|
55
75
|
##
|
76
|
+
# @private
|
56
77
|
# Tries to get the error information from the JSON bodies
|
57
78
|
#
|
58
79
|
# @param body_str [String]
|
59
|
-
# @return [Array(String, String)]
|
80
|
+
# @return [Array(String, String, String, String)]
|
60
81
|
def try_parse_from_body body_str
|
61
82
|
body = JSON.parse body_str
|
62
|
-
return [nil, nil] unless body && body["error"].is_a?(Hash)
|
63
83
|
|
64
|
-
|
65
|
-
|
84
|
+
unless body.is_a?(::Hash) && body&.key?("error") && body["error"].is_a?(::Hash)
|
85
|
+
return [nil, nil, nil, nil]
|
86
|
+
end
|
87
|
+
error = body["error"]
|
88
|
+
|
89
|
+
message = error["message"] if error.key? "message"
|
90
|
+
code = error["code"] if error.key? "code"
|
91
|
+
status = error["status"] if error.key? "status"
|
92
|
+
|
93
|
+
details = parse_details error["details"] if error.key? "details"
|
66
94
|
|
67
|
-
[message, code]
|
95
|
+
[message, code, status, details]
|
68
96
|
rescue JSON::ParserError
|
69
|
-
[nil, nil]
|
97
|
+
[nil, nil, nil, nil]
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# @private
|
102
|
+
# Parses the details data, trying to extract the Protobuf.Any objects
|
103
|
+
# from it, if it's an array of hashes. Otherwise returns it as is.
|
104
|
+
#
|
105
|
+
# @param details [Object, nil] the details object
|
106
|
+
#
|
107
|
+
# @return [Object, nil]
|
108
|
+
def parse_details details
|
109
|
+
# For rest errors details will contain json representations of `Protobuf.Any`
|
110
|
+
# decoded into hashes. If it's not an array, of its elements are not hashes,
|
111
|
+
# it's some other case
|
112
|
+
return details unless details.is_a? ::Array
|
113
|
+
|
114
|
+
details.map do |detail_instance|
|
115
|
+
next detail_instance unless detail_instance.is_a? ::Hash
|
116
|
+
# Next, parse detail_instance into a Proto message.
|
117
|
+
# There are three possible issues for the JSON->Any->message parsing
|
118
|
+
# - json decoding fails
|
119
|
+
# - the json belongs to a proto message type we don't know about
|
120
|
+
# - any unpacking fails
|
121
|
+
# If we hit any of these three issues we'll just return the original hash
|
122
|
+
begin
|
123
|
+
any = ::Google::Protobuf::Any.decode_json detail_instance.to_json
|
124
|
+
klass = ::Google::Protobuf::DescriptorPool.generated_pool.lookup(any.type_name)&.msgclass
|
125
|
+
next detail_instance if klass.nil?
|
126
|
+
unpack = any.unpack klass
|
127
|
+
next detail_instance if unpack.nil?
|
128
|
+
unpack
|
129
|
+
rescue ::Google::Protobuf::ParseError
|
130
|
+
detail_instance
|
131
|
+
end
|
132
|
+
end.compact
|
70
133
|
end
|
71
134
|
end
|
72
135
|
end
|
@@ -0,0 +1,101 @@
|
|
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 Rest
|
19
|
+
##
|
20
|
+
# A class to provide the Enumerable interface to the response of a REST server-streaming dmethod.
|
21
|
+
#
|
22
|
+
# ServerStream provides the enumerations over the individual response messages within the stream.
|
23
|
+
#
|
24
|
+
# @example normal iteration over resources.
|
25
|
+
# server_stream.each { |response| puts response }
|
26
|
+
#
|
27
|
+
class ServerStream
|
28
|
+
include Enumerable
|
29
|
+
|
30
|
+
##
|
31
|
+
# Initializes ServerStream object.
|
32
|
+
#
|
33
|
+
# @param message_klass [Class]
|
34
|
+
# @param json_enumerator [Enumerator<String>]
|
35
|
+
def initialize message_klass, json_enumerator
|
36
|
+
@json_enumerator = json_enumerator
|
37
|
+
@obj = ""
|
38
|
+
@message_klass = message_klass
|
39
|
+
@ready_objs = [] # List of strings
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Iterate over JSON objects in the streamed response.
|
44
|
+
#
|
45
|
+
# @yield [Object] Gives one complete Message object.
|
46
|
+
#
|
47
|
+
# @return [Enumerator] if no block is provided
|
48
|
+
#
|
49
|
+
def each
|
50
|
+
return enum_for :each unless block_given?
|
51
|
+
|
52
|
+
loop do
|
53
|
+
while @ready_objs.length.zero?
|
54
|
+
begin
|
55
|
+
chunk = @json_enumerator.next
|
56
|
+
next unless chunk
|
57
|
+
next_json! chunk
|
58
|
+
rescue StopIteration
|
59
|
+
dangling_content = @obj.strip
|
60
|
+
error_expl = "Dangling content left after iterating through the stream. " \
|
61
|
+
"This means that not all content was received or parsed correctly. " \
|
62
|
+
"It is likely a result of server or network error."
|
63
|
+
error_text = "#{error_expl}\n Content left unparsed: #{dangling_content}"
|
64
|
+
|
65
|
+
raise Gapic::Common::Error, error_text unless dangling_content.empty?
|
66
|
+
return
|
67
|
+
end
|
68
|
+
end
|
69
|
+
yield @message_klass.decode_json @ready_objs.shift, ignore_unknown_fields: true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
##
|
76
|
+
# Builds the next JSON object of the server stream from chunk.
|
77
|
+
#
|
78
|
+
# @param chunk [String] Contains (partial) JSON object
|
79
|
+
#
|
80
|
+
def next_json! chunk
|
81
|
+
chunk.chars.each do |char|
|
82
|
+
# Invariant: @obj is always either a part of a single JSON object or the entire JSON object.
|
83
|
+
# Hence, it's safe to strip whitespace, commans and array brackets. These characters
|
84
|
+
# are only added before @obj is a complete JSON object and essentially can be flushed.
|
85
|
+
next if @obj.empty? && char != "{"
|
86
|
+
@obj += char
|
87
|
+
next unless char == "}"
|
88
|
+
begin
|
89
|
+
# Two choices here: append a Ruby object into
|
90
|
+
# ready_objs or a string. Going with the latter here.
|
91
|
+
JSON.parse @obj
|
92
|
+
@ready_objs.append @obj
|
93
|
+
@obj = ""
|
94
|
+
rescue JSON::ParserError
|
95
|
+
next
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,71 @@
|
|
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
|
+
|
16
|
+
module Gapic
|
17
|
+
module Rest
|
18
|
+
##
|
19
|
+
# @private
|
20
|
+
# A class to provide the Enumerable interface to an incoming stream of data.
|
21
|
+
#
|
22
|
+
# ThreadedEnumerator provides the enumerations over the individual chunks of data received from the server.
|
23
|
+
#
|
24
|
+
# @example normal iteration over resources.
|
25
|
+
# chunk = threaded_enumerator.next
|
26
|
+
#
|
27
|
+
# @attribute [r] in_q
|
28
|
+
# @return [Queue] Input queue.
|
29
|
+
# @attribute [r] out_q
|
30
|
+
# @return [Queue] Output queue.
|
31
|
+
class ThreadedEnumerator
|
32
|
+
attr_reader :in_q
|
33
|
+
attr_reader :out_q
|
34
|
+
|
35
|
+
# Spawns a new thread and does appropriate clean-up
|
36
|
+
# in case thread fails. Propagates exception back
|
37
|
+
# to main thread.
|
38
|
+
#
|
39
|
+
# @yieldparam in_q[Queue] input queue
|
40
|
+
# @yieldparam out_q[Queue] output queue
|
41
|
+
def initialize
|
42
|
+
@in_q = Queue.new
|
43
|
+
@out_q = Queue.new
|
44
|
+
|
45
|
+
Thread.new do
|
46
|
+
yield @in_q, @out_q
|
47
|
+
rescue StandardError => e
|
48
|
+
@out_q.push e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def next
|
53
|
+
@in_q.enq :next
|
54
|
+
chunk = @out_q.deq
|
55
|
+
|
56
|
+
if chunk.is_a? StandardError
|
57
|
+
@out_q.close
|
58
|
+
@in_q.close
|
59
|
+
raise chunk
|
60
|
+
end
|
61
|
+
|
62
|
+
if chunk.nil?
|
63
|
+
@out_q.close
|
64
|
+
@in_q.close
|
65
|
+
raise StopIteration
|
66
|
+
end
|
67
|
+
chunk
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/gapic/rest.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gapic-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.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-
|
11
|
+
date: 2022-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -297,6 +297,7 @@ files:
|
|
297
297
|
- lib/gapic/generic_lro/base_operation.rb
|
298
298
|
- lib/gapic/generic_lro/operation.rb
|
299
299
|
- lib/gapic/grpc.rb
|
300
|
+
- lib/gapic/grpc/errors.rb
|
300
301
|
- lib/gapic/grpc/service_stub.rb
|
301
302
|
- lib/gapic/grpc/service_stub/rpc_call.rb
|
302
303
|
- lib/gapic/grpc/status_details.rb
|
@@ -313,6 +314,8 @@ files:
|
|
313
314
|
- lib/gapic/rest/grpc_transcoder/http_binding.rb
|
314
315
|
- lib/gapic/rest/operation.rb
|
315
316
|
- lib/gapic/rest/paged_enumerable.rb
|
317
|
+
- lib/gapic/rest/server_stream.rb
|
318
|
+
- lib/gapic/rest/threaded_enumerator.rb
|
316
319
|
- lib/gapic/stream_input.rb
|
317
320
|
homepage: https://github.com/googleapis/gapic-generator-ruby
|
318
321
|
licenses:
|