Protocol::GRPCSourceProtocolGRPCMetadata

module Metadata

Definitions

def self.extract_status(headers)

Extract gRPC status from headers. Convenience method that handles both Header::Status instances and raw values. Returns Status::UNKNOWN if status is not present.

Note: In Protocol::HTTP::Headers, trailers are merged into the headers so users just access headers["grpc-status"] regardless of whether it was sent as an initial header or trailer.

Signature

parameter headers Protocol::HTTP::Headers
returns Integer

Status code (0-16)

Implementation

def self.extract_status(headers)
	# Ensure policy is set - setting policy clears the index (@indexed = nil)
	# The index will be rebuilt automatically on next access via to_h
	headers.policy = Protocol::GRPC::HEADER_POLICY unless headers.policy == Protocol::GRPC::HEADER_POLICY
	
	status = headers["grpc-status"]
	return Status::UNKNOWN unless status
	
	if status.is_a?(Header::Status)
		status.to_i
	else
		# Fallback for when header policy isn't used
		# Handle Array case (may occur with external clients)
		status_value = if status.is_a?(Array)
			# Flatten and take first non-nil value, recursively handle nested arrays
			flattened = status.flatten.compact.first
			# If still an array, take first element
			flattened.is_a?(Array) ? flattened.first : flattened
		else
			status
		end
		
		# Convert to string then integer to handle various types
		# Handle case where status_value might still be an array somehow
		if status_value.is_a?(Array)
			status_value = status_value.first
		end
		status_value.to_s.to_i
	end
end

def self.extract_message(headers)

Extract gRPC status message from headers. Convenience method that handles both Header::Message instances and raw values. Returns Nil if message is not present.

Signature

parameter headers Protocol::HTTP::Headers
returns String | Nil

Status message

Implementation

def self.extract_message(headers)
	# Ensure policy is set - setting policy clears the index (@indexed = nil)
	# The index will be rebuilt automatically on next access via to_h
	headers.policy = Protocol::GRPC::HEADER_POLICY unless headers.policy == Protocol::GRPC::HEADER_POLICY
	
	message = headers["grpc-message"]
	return nil unless message
	
	if message.is_a?(Header::Message)
		message.decode
	else
		# Fallback for when header policy isn't used
		message_value = message.is_a?(Array) ? message.first : message.to_s
		URI.decode_www_form_component(message_value)
	end
end

def self.add_status!(headers, status: Status::OK, message: nil, error: nil)

Add gRPC status, message, and optional backtrace to headers. Whether these become headers or trailers is controlled by the protocol layer.

Signature

parameter headers Protocol::HTTP::Headers
parameter status Integer

gRPC status code

parameter message String | Nil

Optional status message

parameter error Exception | Nil

Optional error object (used to extract backtrace)

Implementation

def self.add_status!(headers, status: Status::OK, message: nil, error: nil)
	headers["grpc-status"] = Header::Status.new(status)
	headers["grpc-message"] = Header::Message.new(Header::Message.encode(message)) if message
	
	# Add backtrace from error if available
	if error && error.backtrace && !error.backtrace.empty?
		# Assign backtrace array directly - Split header will handle it
		headers["backtrace"] = error.backtrace
	end
end