aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar apolcyn <apolcyn@google.com>2017-09-27 14:40:14 -0700
committerGravatar GitHub <noreply@github.com>2017-09-27 14:40:14 -0700
commit8eeb7ce9c000e3c9fb1d06c8775972056db2e5d0 (patch)
treebdd1ca5c46d0618bca174d4b7fce1bbead7d6bdf /src
parent56e4b8e67ce18fc018425c53cd7587bc9404033c (diff)
parentf1b1ab08994f3f269c0128a87dd3355fa4839a85 (diff)
Merge pull request #12721 from apolcyn/google_rpc_status_fix_not_present_case
Make ruby google RPC status conversion return nil if the status-details trailer was missing
Diffstat (limited to 'src')
-rw-r--r--src/ruby/lib/grpc/google_rpc_status_utils.rb9
-rw-r--r--src/ruby/spec/google_rpc_status_utils_spec.rb77
2 files changed, 81 insertions, 5 deletions
diff --git a/src/ruby/lib/grpc/google_rpc_status_utils.rb b/src/ruby/lib/grpc/google_rpc_status_utils.rb
index fdadd6b76e..f253b082b6 100644
--- a/src/ruby/lib/grpc/google_rpc_status_utils.rb
+++ b/src/ruby/lib/grpc/google_rpc_status_utils.rb
@@ -19,10 +19,17 @@ require 'google/rpc/status_pb'
module GRPC
# GoogleRpcStatusUtils provides utilities to convert between a
# GRPC::Core::Status and a deserialized Google::Rpc::Status proto
+ # Returns nil if the grpc-status-details-bin trailer could not be
+ # converted to a GoogleRpcStatus due to the server not providing
+ # the necessary trailers.
+ # Raises an error if the server did provide the necessary trailers
+ # but they fail to deseriliaze into a GoogleRpcStatus protobuf.
class GoogleRpcStatusUtils
def self.extract_google_rpc_status(status)
fail ArgumentError, 'bad type' unless status.is_a? Struct::Status
- Google::Rpc::Status.decode(status.metadata['grpc-status-details-bin'])
+ grpc_status_details_bin_trailer = 'grpc-status-details-bin'
+ return nil if status.metadata[grpc_status_details_bin_trailer].nil?
+ Google::Rpc::Status.decode(status.metadata[grpc_status_details_bin_trailer])
end
end
end
diff --git a/src/ruby/spec/google_rpc_status_utils_spec.rb b/src/ruby/spec/google_rpc_status_utils_spec.rb
index fe221c30dd..6f2a06b1d9 100644
--- a/src/ruby/spec/google_rpc_status_utils_spec.rb
+++ b/src/ruby/spec/google_rpc_status_utils_spec.rb
@@ -31,12 +31,11 @@ describe 'conversion from a status struct to a google protobuf status' do
expect(exception.message.include?('bad type')).to be true
end
- it 'fails with some error if the header key is missing' do
+ it 'returns nil if the header key is missing' do
status = Struct::Status.new(1, 'details', key: 'val')
expect(status.metadata.nil?).to be false
- expect do
- GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(status)
- end.to raise_error(StandardError)
+ expect(GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
+ status)).to be(nil)
end
it 'fails with some error if the header key fails to deserialize' do
@@ -221,3 +220,73 @@ describe 'receving a google rpc status from a remote endpoint' do
status_from_exception)).to eq(rpc_status)
end
end
+
+# A test service that fails without explicitly setting the
+# grpc-status-details-bin trailer. Tests assumptions about value
+# of grpc-status-details-bin on the client side when the trailer wasn't
+# set explicitly.
+class NoStatusDetailsBinTestService
+ include GRPC::GenericService
+ rpc :an_rpc, EchoMsg, EchoMsg
+
+ def an_rpc(_, _)
+ fail GRPC::Unknown
+ end
+end
+
+NoStatusDetailsBinTestServiceStub = NoStatusDetailsBinTestService.rpc_stub_class
+
+describe 'when the endpoint doesnt send grpc-status-details-bin' do
+ def start_server
+ @srv = GRPC::RpcServer.new(pool_size: 1)
+ @server_port = @srv.add_http2_port('localhost:0',
+ :this_port_is_insecure)
+ @srv.handle(NoStatusDetailsBinTestService)
+ @server_thd = Thread.new { @srv.run }
+ @srv.wait_till_running
+ end
+
+ def stop_server
+ expect(@srv.stopped?).to be(false)
+ @srv.stop
+ @server_thd.join
+ expect(@srv.stopped?).to be(true)
+ end
+
+ before(:each) do
+ start_server
+ end
+
+ after(:each) do
+ stop_server
+ end
+
+ it 'should receive nil when we extract try to extract a google '\
+ 'rpc status from a BadStatus exception that didnt have it' do
+ stub = NoStatusDetailsBinTestServiceStub.new("localhost:#{@server_port}",
+ :this_channel_is_insecure)
+ begin
+ stub.an_rpc(EchoMsg.new)
+ rescue GRPC::Unknown => e
+ rpc_status = GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
+ e.to_status)
+ end
+ expect(rpc_status).to be(nil)
+ end
+
+ it 'should receive nil when we extract try to extract a google '\
+ 'rpc status from an op views status object that didnt have it' do
+ stub = NoStatusDetailsBinTestServiceStub.new("localhost:#{@server_port}",
+ :this_channel_is_insecure)
+ op = stub.an_rpc(EchoMsg.new, return_op: true)
+ begin
+ op.execute
+ rescue GRPC::Unknown => e
+ status_from_exception = e.to_status
+ end
+ expect(GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
+ status_from_exception)).to be(nil)
+ expect(GRPC::GoogleRpcStatusUtils.extract_google_rpc_status(
+ op.status)).to be nil
+ end
+end