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
headersProtocol::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
headersProtocol::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
headersProtocol::HTTP::Headers -
parameter
statusInteger gRPC status code
-
parameter
messageString | Nil Optional status message
-
parameter
errorException | 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