protocol-grpc 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13f745749ba7c9ac86eff356ee01f6d655c3996a1633ab9091c76e4776e41705
4
- data.tar.gz: 9428aba4ba76ca6fb8d3ee751a102f7fc249e27a6630a961b27504da27b3444e
3
+ metadata.gz: 5ead258154cb8fe775c509d2b4aa05aadee904b18f052ff72163559c45ffdae0
4
+ data.tar.gz: 5af2daafbecc85fcd2fa722f9c8e02a262997e0a7fe1fdc0196fab7af80cf2aa
5
5
  SHA512:
6
- metadata.gz: ba9a029154bfad46d73a4f844799508f5ca384042bbbfb832281b4f735dfdf93ddc8ff53f0363d636b8b94d52d6cabdfcefc7d624f2ba16f63e500700789bab8
7
- data.tar.gz: 35c83469b178ad06bf0e3b36bb52683f07f8b8d4e7c2d9e331b32dde6b74bf74748ac925627f822a733c748b9bb84f3875675c5929742e3a1e5d164c265babd7
6
+ metadata.gz: 1e417c6adce8b055da14fd619381f3de243022ed2e9a27841cb2fab0c0c5232c57bbd559728cfcbf72e1ab61e49981f93d100cde21d3a4d194c0f17a89bc1087
7
+ data.tar.gz: 88290f4fb1f059056e0a545eaae4d90efcb4c7b01e69937ecfa17370392092edd66ce178ed1ebab68da3fbb90bfe879ff02ac6ea20f9768e377faa01c7445aa4
checksums.yaml.gz.sig CHANGED
Binary file
data/design.md CHANGED
@@ -140,7 +140,7 @@ module Protocol
140
140
 
141
141
  # Parse service and method from gRPC path
142
142
  # @parameter path [String] e.g., "/my_service.Greeter/SayHello"
143
- # @returns [Array(String, String)] [service, method]
143
+ # @returns [Tuple(String, String)] of service and method.
144
144
  def self.parse_path(path)
145
145
  parts = path.split("/")
146
146
  [parts[1], parts[2]]
@@ -287,7 +287,7 @@ module Protocol
287
287
 
288
288
  # Extract gRPC status message from headers
289
289
  # @parameter headers [Protocol::HTTP::Headers]
290
- # @returns [String, nil] Status message
290
+ # @returns [String | Nil] Status message
291
291
  def self.extract_message(headers)
292
292
  message = headers["grpc-message"]
293
293
  message ? URI.decode_www_form_component(message) : nil
@@ -329,7 +329,7 @@ module Protocol
329
329
  # @parameter body [Protocol::HTTP::Body::Readable] The underlying HTTP body
330
330
  # @parameter message_class [Class, nil] Protobuf message class with .decode method
331
331
  # If nil, returns raw binary data (useful for channel adapters)
332
- # @parameter encoding [String, nil] Compression encoding (from grpc-encoding header)
332
+ # @parameter encoding [String | Nil] Compression encoding (from grpc-encoding header)
333
333
  def initialize(body, message_class: nil, encoding: nil)
334
334
  super(body)
335
335
  @message_class = message_class
@@ -408,7 +408,7 @@ module Protocol
408
408
  # Writes length-prefixed gRPC messages
409
409
  # This is the standard writable body for gRPC - all gRPC requests use message framing
410
410
  class Writable < Protocol::HTTP::Body::Writable
411
- # @parameter encoding [String, nil] Compression encoding (gzip, deflate, identity)
411
+ # @parameter encoding [String | Nil] Compression encoding (gzip, deflate, identity)
412
412
  # @parameter level [Integer] Compression level if encoding is used
413
413
  def initialize(encoding: nil, level: Zlib::DEFAULT_COMPRESSION, **options)
414
414
  super(**options)
@@ -574,7 +574,7 @@ module Protocol
574
574
  end
575
575
 
576
576
  # Get peer information (client address)
577
- # @returns [String, nil]
577
+ # @returns [String | Nil]
578
578
  def peer
579
579
  @request.peer&.to_s
580
580
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require "uri"
7
+
8
+ module Protocol
9
+ module GRPC
10
+ module Header
11
+ # The `grpc-message` header represents the gRPC status message.
12
+ #
13
+ # The `grpc-message` header contains a human-readable error message, URL-encoded according to RFC 3986.
14
+ # This header is optional and typically only present when there's an error (non-zero status code).
15
+ # This header can appear both as an initial header (for trailers-only responses) and as a trailer.
16
+ class Message < String
17
+ # Parse a message from a header value.
18
+ #
19
+ # @parameter value [String] The header value to parse.
20
+ # @returns [Message] A new Message instance.
21
+ def self.parse(value)
22
+ new(value)
23
+ end
24
+
25
+ # Initialize the message header with the given value.
26
+ #
27
+ # @parameter value [String] The message value (will be URL-encoded if not already encoded).
28
+ def initialize(value)
29
+ super(value)
30
+ end
31
+
32
+ # Decode the URL-encoded message.
33
+ #
34
+ # @returns [String] The decoded message.
35
+ def decode
36
+ ::URI.decode_www_form_component(self)
37
+ end
38
+
39
+ # Encode the message for use in headers.
40
+ #
41
+ # @parameter message [String] The message to encode.
42
+ # @returns [String] The URL-encoded message.
43
+ def self.encode(message)
44
+ URI.encode_www_form_component(message).gsub("+", "%20")
45
+ end
46
+
47
+ # Merge another message value (takes the new value, as message should only appear once)
48
+ # @parameter value [String] The new message value
49
+ def <<(value)
50
+ replace(value.to_s)
51
+
52
+ return self
53
+ end
54
+
55
+ # Whether this header is acceptable in HTTP trailers.
56
+ # The `grpc-message` header can appear in trailers as per the gRPC specification.
57
+ # @returns [Boolean] `true`, as grpc-message can appear in trailers.
58
+ def self.trailer?
59
+ true
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require "protocol/http"
7
+
8
+ module Protocol
9
+ module GRPC
10
+ module Header
11
+ # Base class for custom gRPC metadata (allowed in trailers).
12
+ class Metadata < Protocol::HTTP::Header::Split
13
+ # Whether this header is acceptable in HTTP trailers.
14
+ # The `grpc-metadata` header can appear in trailers as per the gRPC specification.
15
+ # @returns [Boolean] `true`, as grpc-metadata can appear in trailers.
16
+ def self.trailer?
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ module Protocol
7
+ module GRPC
8
+ module Header
9
+ # The `grpc-status` header represents the gRPC status code.
10
+ #
11
+ # The `grpc-status` header contains a numeric status code (0-16) indicating the result of the RPC call.
12
+ # Status code 0 indicates success (OK), while other codes indicate various error conditions.
13
+ # This header can appear both as an initial header (for trailers-only responses) and as a trailer.
14
+ class Status
15
+ # Parse a status code from a header value.
16
+ #
17
+ # @parameter value [String] The header value to parse.
18
+ # @returns [Status] A new Status instance.
19
+ def self.parse(value)
20
+ new(value.to_i)
21
+ end
22
+
23
+ # Initialize the status header with the given value.
24
+ #
25
+ # @parameter value [String | Integer] The status code as a string or integer.
26
+ def initialize(value)
27
+ @value = value.to_i
28
+ end
29
+
30
+ # Get the status code as an integer.
31
+ #
32
+ # @returns [Integer] The status code.
33
+ def to_i
34
+ @value
35
+ end
36
+
37
+ # Serialize the status code to a string.
38
+ #
39
+ # @returns [String] The status code as a string.
40
+ def to_s
41
+ @value.to_s
42
+ end
43
+
44
+ # Check equality with another status or integer value.
45
+ #
46
+ # @parameter other [Status | Integer] The value to compare with.
47
+ # @returns [Boolean] if the status codes are equal.
48
+ def ==(other)
49
+ @value == other.to_i
50
+ end
51
+
52
+ alias eql? ==
53
+
54
+ # Generate hash for use in Hash/Set collections.
55
+ #
56
+ # @returns [Integer] The hash value based on the status code.
57
+ def hash
58
+ @value.hash
59
+ end
60
+
61
+ # Check if this status represents success (status code 0).
62
+ #
63
+ # @returns [Boolean] `true` if the status code is 0 (OK).
64
+ def ok?
65
+ @value == 0
66
+ end
67
+
68
+ # Merge another status value (takes the new value, as status should only appear once)
69
+ # @parameter value [String | Integer] The new status code
70
+ def <<(value)
71
+ @value = value.to_i
72
+
73
+ return self
74
+ end
75
+
76
+ # Whether this header is acceptable in HTTP trailers.
77
+ # The `grpc-status` header can appear in trailers as per the gRPC specification.
78
+ # @returns [Boolean] `true`, as grpc-status can appear in trailers.
79
+ def self.trailer?
80
+ true
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -4,120 +4,16 @@
4
4
  # Copyright, 2025, by Samuel Williams.
5
5
 
6
6
  require "protocol/http"
7
- require "uri"
8
7
 
9
8
  require_relative "status"
9
+ require_relative "header/status"
10
+ require_relative "header/message"
11
+ require_relative "header/metadata"
10
12
 
11
13
  module Protocol
12
14
  module GRPC
13
15
  # @namespace
14
16
  module Header
15
- # The `grpc-status` header represents the gRPC status code.
16
- #
17
- # The `grpc-status` header contains a numeric status code (0-16) indicating the result of the RPC call.
18
- # Status code 0 indicates success (OK), while other codes indicate various error conditions.
19
- # This header can appear both as an initial header (for trailers-only responses) and as a trailer.
20
- class Status
21
- # Initialize the status header with the given value.
22
- #
23
- # @parameter value [String, Integer, Array] The status code as a string, integer, or array (takes first element).
24
- def initialize(value)
25
- @value = normalize_value(value)
26
- end
27
-
28
- # Get the status code as an integer.
29
- #
30
- # @returns [Integer] The status code.
31
- def to_i
32
- @value
33
- end
34
-
35
- # Serialize the status code to a string.
36
- #
37
- # @returns [String] The status code as a string.
38
- def to_s
39
- @value.to_s
40
- end
41
-
42
- # Merge another status value (takes the new value, as status should only appear once)
43
- # @parameter value [String, Integer, Array] The new status code
44
- def <<(value)
45
- @value = normalize_value(value)
46
- self
47
- end
48
-
49
- private
50
-
51
- # Normalize a value to an integer status code.
52
- # Handles arrays (from external clients), strings, and integers.
53
- # @parameter value [String, Integer, Array] The raw value
54
- # @returns [Integer] The normalized status code
55
- def normalize_value(value)
56
- # Handle Array case (may occur with external clients)
57
- actual_value = value.is_a?(Array) ? value.flatten.compact.first : value
58
- actual_value.to_i
59
- end
60
-
61
- # Whether this header is acceptable in HTTP trailers.
62
- # The `grpc-status` header can appear in trailers as per the gRPC specification.
63
- # @returns [Boolean] `true`, as grpc-status can appear in trailers.
64
- def self.trailer?
65
- true
66
- end
67
- end
68
-
69
- # The `grpc-message` header represents the gRPC status message.
70
- #
71
- # The `grpc-message` header contains a human-readable error message, URL-encoded according to RFC 3986.
72
- # This header is optional and typically only present when there's an error (non-zero status code).
73
- # This header can appear both as an initial header (for trailers-only responses) and as a trailer.
74
- class Message < String
75
- # Initialize the message header with the given value.
76
- #
77
- # @parameter value [String] The message value (will be URL-encoded if not already encoded).
78
- def initialize(value)
79
- super(value.to_s)
80
- end
81
-
82
- # Decode the URL-encoded message.
83
- #
84
- # @returns [String] The decoded message.
85
- def decode
86
- URI.decode_www_form_component(self)
87
- end
88
-
89
- # Encode the message for use in headers.
90
- #
91
- # @parameter message [String] The message to encode.
92
- # @returns [String] The URL-encoded message.
93
- def self.encode(message)
94
- URI.encode_www_form_component(message).gsub("+", "%20")
95
- end
96
-
97
- # Merge another message value (takes the new value, as message should only appear once)
98
- # @parameter value [String] The new message value
99
- def <<(value)
100
- replace(value.to_s)
101
- self
102
- end
103
-
104
- # Whether this header is acceptable in HTTP trailers.
105
- # The `grpc-message` header can appear in trailers as per the gRPC specification.
106
- # @returns [Boolean] `true`, as grpc-message can appear in trailers.
107
- def self.trailer?
108
- true
109
- end
110
- end
111
-
112
- # Base class for custom gRPC metadata (allowed in trailers).
113
- class Metadata < Protocol::HTTP::Header::Split
114
- # Whether this header is acceptable in HTTP trailers.
115
- # The `grpc-metadata` header can appear in trailers as per the gRPC specification.
116
- # @returns [Boolean] `true`, as grpc-metadata can appear in trailers.
117
- def self.trailer?
118
- true
119
- end
120
- end
121
17
  end
122
18
 
123
19
  # Custom header policy for gRPC.
@@ -10,6 +10,8 @@ module Protocol
10
10
  # Wrapper class to mark a message type as streamed.
11
11
  # Used with the stream() helper method in RPC definitions.
12
12
  class Streaming
13
+ # Initialize a new Streaming wrapper.
14
+ # @parameter message_class [Class] The message class being wrapped
13
15
  def initialize(message_class)
14
16
  @message_class = message_class
15
17
  end
@@ -148,7 +150,7 @@ module Protocol
148
150
  attr :name
149
151
 
150
152
  # Build gRPC path for a method.
151
- # @parameter method_name [String, Symbol] Method name in PascalCase (e.g., :SayHello)
153
+ # @parameter method_name [String | Symbol] Method name in PascalCase (e.g., :SayHello)
152
154
  # @returns [String] gRPC path with PascalCase method name
153
155
  def path(method_name)
154
156
  Methods.build_path(@name, method_name.to_s)
@@ -20,7 +20,7 @@ module Protocol
20
20
 
21
21
  # Parse service and method from gRPC path.
22
22
  # @parameter path [String] e.g., "/my_service.Greeter/SayHello"
23
- # @returns [Array(String, String)] [service, method]
23
+ # @returns [Array(String | String)] [service, method]
24
24
  def self.parse_path(path)
25
25
  parts = path.split("/")
26
26
  [parts[1], parts[2]]
@@ -7,7 +7,7 @@
7
7
  module Protocol
8
8
  # @namespace
9
9
  module GRPC
10
- VERSION = "0.6.0"
10
+ VERSION = "0.7.0"
11
11
  end
12
12
  end
13
13
 
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-grpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -109,6 +109,9 @@ files:
109
109
  - lib/protocol/grpc/call.rb
110
110
  - lib/protocol/grpc/error.rb
111
111
  - lib/protocol/grpc/header.rb
112
+ - lib/protocol/grpc/header/message.rb
113
+ - lib/protocol/grpc/header/metadata.rb
114
+ - lib/protocol/grpc/header/status.rb
112
115
  - lib/protocol/grpc/health_check.rb
113
116
  - lib/protocol/grpc/interface.rb
114
117
  - lib/protocol/grpc/metadata.rb
@@ -139,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
142
  - !ruby/object:Gem::Version
140
143
  version: '0'
141
144
  requirements: []
142
- rubygems_version: 3.6.9
145
+ rubygems_version: 4.0.3
143
146
  specification_version: 4
144
147
  summary: Protocol abstractions for gRPC, built on top of protocol-http.
145
148
  test_files: []
metadata.gz.sig CHANGED
Binary file