module GRPCWeb::ClientExecutor
Client
execution concerns
Constants
- GRPC_HEADERS
- GRPC_MESSAGE_HEADER
- GRPC_STATUS_HEADER
Public Class Methods
request(uri, rpc_desc, params = {})
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 19 def request(uri, rpc_desc, params = {}) req_proto = rpc_desc.input.new(params) marshalled_proto = rpc_desc.marshal_proc.call(req_proto) frame = ::GRPCWeb::MessageFrame.payload_frame(marshalled_proto) request_body = ::GRPCWeb::MessageFraming.pack_frames([frame]) resp = post_request(uri, request_body) resp_body = handle_response(resp) rpc_desc.unmarshal_proc(:output).call(resp_body) end
Private Class Methods
extract_headers(frames)
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 66 def extract_headers(frames) header_frame = frames.find(&:header?) if header_frame parse_headers(header_frame.body) else {} end end
handle_response(resp)
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 53 def handle_response(resp) begin frames = ::GRPCWeb::MessageFraming.unpack_frames(resp.body) headers = extract_headers(frames) rescue StandardError headers = {} error_unpacking_frames = true end raise_on_response_errors(resp, headers, error_unpacking_frames) frames.find(&:payload?).body end
parse_headers(header_str)
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 75 def parse_headers(header_str) headers = {} lines = header_str.split(/\r?\n/) lines.each do |line| key, value = line.split(':', 2) headers[key] = value end headers end
post_request(uri, request_body)
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 39 def post_request(uri, request_body) request = Net::HTTP::Post.new(uri, request_headers) request.body = request_body request.basic_auth uri.user, uri.password if uri.userinfo begin Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(request) end rescue StandardError => e raise ::GRPC::Unavailable, e.message end end
raise_on_response_errors(resp, headers, error_unpacking_frames)
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 85 def raise_on_response_errors(resp, headers, error_unpacking_frames) metadata = headers.reject { |key, _| GRPC_HEADERS.include?(key) } status_str = headers[GRPC_STATUS_HEADER] status_code = status_str.to_i if status_str && status_str == status_str.to_i.to_s # see https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md if status_code && status_code != 0 raise ::GRPC::BadStatus.new_status_exception( status_code, headers[GRPC_MESSAGE_HEADER], metadata, ) end case resp when Net::HTTPBadRequest # 400 raise ::GRPC::Internal.new(resp.message, metadata) when Net::HTTPUnauthorized # 401 raise ::GRPC::Unauthenticated.new(resp.message, metadata) when Net::HTTPForbidden # 403 raise ::GRPC::PermissionDenied.new(resp.message, metadata) when Net::HTTPNotFound # 404 raise ::GRPC::Unimplemented.new(resp.message, metadata) when Net::HTTPTooManyRequests, # 429 Net::HTTPBadGateway, # 502 Net::HTTPServiceUnavailable, # 503 Net::HTTPGatewayTimeOut # 504 raise ::GRPC::Unavailable.new(resp.message, metadata) else raise ::GRPC::Unknown.new(resp.message, metadata) unless resp.is_a?(Net::HTTPSuccess) # 200 raise ::GRPC::Internal.new(resp.message, metadata) if error_unpacking_frames raise ::GRPC::Unknown.new(resp.message, metadata) if status_code.nil? end end
request_headers()
click to toggle source
# File lib/grpc_web/client/client_executor.rb, line 32 def request_headers { 'Accept' => PROTO_CONTENT_TYPE, 'Content-Type' => PROTO_CONTENT_TYPE, } end