lib/httpx/plugins/grpc.rb in httpx-0.15.4 vs lib/httpx/plugins/grpc.rb in httpx-0.16.0

- old
+ new

@@ -47,11 +47,10 @@ }.freeze class << self def load_dependencies(*) require "stringio" - require "google/protobuf" require "httpx/plugins/grpc/message" require "httpx/plugins/grpc/call" end def configure(klass) @@ -59,49 +58,51 @@ klass.plugin(:compression) klass.plugin(:stream) end def extra_options(options) - Class.new(options.class) do - def_option(:grpc_service, <<-OUT) - String(value) - OUT - - def_option(:grpc_compression, <<-OUT) - case value - when true, false - value - else - value.to_s - end - OUT - - def_option(:grpc_rpcs, <<-OUT) - Hash[value] - OUT - - def_option(:grpc_deadline, <<-OUT) - raise Error, ":grpc_deadline must be positive" unless value.positive? - - value - OUT - - def_option(:call_credentials, <<-OUT) - raise Error, ":call_credentials must respond to #call" unless value.respond_to?(:call) - - value - OUT - end.new(options).merge( + options.merge( fallback_protocol: "h2", http2_settings: { wait_for_handshake: false }, grpc_rpcs: {}.freeze, grpc_compression: false, grpc_deadline: DEADLINE ) end end + module OptionsMethods + def option_grpc_service(value) + String(value) + end + + def option_grpc_compression(value) + case value + when true, false + value + else + value.to_s + end + end + + def option_grpc_rpcs(value) + Hash[value] + end + + def option_grpc_deadline(value) + raise TypeError, ":grpc_deadline must be positive" unless value.positive? + + value + end + + def option_call_credentials(value) + raise TypeError, ":call_credentials must respond to #call" unless value.respond_to?(:call) + + value + end + end + module ResponseMethods attr_reader :trailing_metadata def merge_headers(trailers) @trailing_metadata = Hash[trailers] @@ -138,21 +139,56 @@ rpc_opts = { deadline: @options.grpc_deadline, }.merge(opts) - with(grpc_rpcs: @options.grpc_rpcs.merge( - rpc_name.underscore => [rpc_name, input, output, rpc_opts] - ).freeze) + session_class = Class.new(self.class) do + class_eval(<<-OUT, __FILE__, __LINE__ + 1) + def #{rpc_name}(input, **opts) + rpc_execute("#{rpc_name}", input, **opts) + end + OUT + end + + session_class.new(@options.merge( + grpc_rpcs: @options.grpc_rpcs.merge( + rpc_name.underscore => [rpc_name, input, output, rpc_opts] + ).freeze + )) end def build_stub(origin, service: nil, compression: false) scheme = @options.ssl.empty? ? "http" : "https" origin = URI.parse("#{scheme}://#{origin}") - with(origin: origin, grpc_service: service, grpc_compression: compression) + session = self + + if service && service.respond_to?(:rpc_descs) + # it's a grpc generic service + service.rpc_descs.each do |rpc_name, rpc_desc| + rpc_opts = { + marshal_method: rpc_desc.marshal_method, + unmarshal_method: rpc_desc.unmarshal_method, + } + + input = rpc_desc.input + input = input.type if input.respond_to?(:type) + + output = rpc_desc.output + if output.respond_to?(:type) + rpc_opts[:stream] = true + output = output.type + end + + session = session.rpc(rpc_name, input, output, **rpc_opts) + end + + service = service.service_name + end + + session.with(origin: origin, grpc_service: service, grpc_compression: compression) end def execute(rpc_method, input, deadline: DEADLINE, metadata: nil, @@ -164,11 +200,11 @@ end private def rpc_execute(rpc_name, input, **opts) - rpc_name, input_enc, output_enc, rpc_opts = @options.grpc_rpcs[rpc_name.to_s] || raise(Error, "#{rpc_name}: undefined service") + rpc_name, input_enc, output_enc, rpc_opts = @options.grpc_rpcs[rpc_name] exec_opts = rpc_opts.merge(opts) marshal_method ||= exec_opts.delete(:marshal_method) || MARSHAL_METHOD unmarshal_method ||= exec_opts.delete(:unmarshal_method) || UNMARSHAL_METHOD @@ -227,19 +263,9 @@ else Message.encode(input, deflater: deflater) end build_request(:post, uri, headers: headers, body: body) - end - - def respond_to_missing?(meth, *, &blk) - @options.grpc_rpcs.key?(meth.to_s) || super - end - - def method_missing(meth, *args, **kwargs, &blk) - return rpc_execute(meth, *args, **kwargs, &blk) if @options.grpc_rpcs.key?(meth.to_s) - - super end end end register_plugin :grpc, GRPC end