Protocol::GRPCSourceProtocolGRPCMethods

module Methods

Provides utility methods for building and parsing gRPC-compatible HTTP requests.

Definitions

def self.build_path(service, method)

Build gRPC path from service and method.

Signature

parameter service String

e.g., "my_service.Greeter"

parameter method String

e.g., "SayHello"

returns String

e.g., "/my_service.Greeter/SayHello"

Implementation

def self.build_path(service, method)
	"/#{service}/#{method}"
end

def self.parse_path(path)

Parse service and method from gRPC path.

Signature

parameter path String

e.g., "/my_service.Greeter/SayHello"

returns Array(String, String)

[service, method]

Implementation

def self.parse_path(path)
	parts = path.split("/")
	[parts[1], parts[2]]
end

def self.build_headers(metadata: {}, timeout: nil, content_type: "application/grpc+proto")

Build gRPC request headers.

Signature

parameter metadata Hash

Custom metadata key-value pairs

parameter timeout Numeric | Nil

Optional timeout in seconds

parameter content_type String

Content type (default: "application/grpc+proto")

returns Protocol::HTTP::Headers

Implementation

def self.build_headers(metadata: {}, timeout: nil, content_type: "application/grpc+proto")
	headers = Protocol::HTTP::Headers.new
	headers["content-type"] = content_type
	headers["te"] = "trailers"
	headers["grpc-timeout"] = format_timeout(timeout) if timeout
	
	metadata.each do |key, value|
		# Binary headers end with -bin and are base64 encoded:
		headers[key] = if key.end_with?("-bin")
			Base64.strict_encode64(value)
		else
			value.to_s
		end
	end
	
	headers
end

def self.extract_metadata(headers)

Extract metadata from gRPC headers.

Signature

parameter headers Protocol::HTTP::Headers
returns Hash

Metadata key-value pairs

Implementation

def self.extract_metadata(headers)
	metadata = {}
	
	headers.each do |key, value|
		# Skip reserved headers:
		next if key.start_with?("grpc-") || key == "content-type" || key == "te"
		
		# Decode binary headers:
		metadata[key] = if key.end_with?("-bin")
			Base64.strict_decode64(value)
		else
			value
		end
	end
	
	metadata
end

def self.format_timeout(timeout)

Format timeout for grpc-timeout header.

Signature

parameter timeout Numeric

Timeout in seconds

returns String

e.g., "1000m" for 1 second

Implementation

def self.format_timeout(timeout)
	# gRPC timeout format: value + unit (H=hours, M=minutes, S=seconds, m=milliseconds, u=microseconds, n=nanoseconds)
	if timeout >= 3600
		"#{(timeout / 3600).to_i}H"
	elsif timeout >= 60
		"#{(timeout / 60).to_i}M"
	elsif timeout >= 1
		"#{timeout.to_i}S"
	elsif timeout >= 0.001
		"#{(timeout * 1000).to_i}m"
	elsif timeout >= 0.000001
		"#{(timeout * 1_000_000).to_i}u"
	else
		"#{(timeout * 1_000_000_000).to_i}n"
	end
end

def self.parse_timeout(value)

Parse grpc-timeout header value.

Signature

parameter value String

e.g., "1000m"

returns Numeric | Nil

Timeout in seconds, or Nil if value is invalid

Implementation

def self.parse_timeout(value)
	return nil unless value
	
	amount = value[0...-1].to_i
	unit = value[-1]
	
	case unit
	when "H" then amount * 3600
	when "M" then amount * 60
	when "S" then amount
	when "m" then amount / 1000.0
	when "u" then amount / 1_000_000.0
	when "n" then amount / 1_000_000_000.0
	end
end