protocol-grpc 0.12.0 → 0.13.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/getting-started.md +7 -9
- data/design.md +21 -28
- data/lib/protocol/grpc/call.rb +2 -2
- data/lib/protocol/grpc/interface.rb +2 -2
- data/lib/protocol/grpc/metadata.rb +55 -1
- data/lib/protocol/grpc/methods.rb +16 -45
- data/lib/protocol/grpc/route.rb +48 -0
- data/lib/protocol/grpc/version.rb +1 -1
- data/lib/protocol/grpc.rb +2 -1
- data/readme.md +5 -0
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +2 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a991dcf85eaa66f7a1cbd8d31c919e82b37e0b2034ad594da58d342391b00590
|
|
4
|
+
data.tar.gz: 0fe139aeffb04fbaee3700bcfde98588625dc37706195598fa99dd632786396a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cbd273eb5cb2481235b14404bdc2742f95b3dee7a53383e1a69926e5b93508e2701bbba165d26023953b73cd9cc1438872d3fffa9dd1e77f2c5f0116c2ec95ce
|
|
7
|
+
data.tar.gz: 7e532651a9629d38558c1078eb98fb97b13c4d3c999d13ef22e01d8f6e31822bfdd10c11ce7e9640eb42db393f3441420e804fc7c6d6b74ddcdc49b3ceef560e
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/getting-started.md
CHANGED
|
@@ -62,11 +62,10 @@ rpc :SayHelloAgain, request_class: Hello::HelloRequest, response_class: Hello::H
|
|
|
62
62
|
|
|
63
63
|
### Building a Request
|
|
64
64
|
|
|
65
|
-
Build gRPC requests using `Protocol::GRPC::
|
|
65
|
+
Build gRPC requests using `Protocol::GRPC::Metadata`, `Protocol::GRPC::Route`, and `Protocol::GRPC::Body::Writable`:
|
|
66
66
|
|
|
67
67
|
``` ruby
|
|
68
68
|
require "protocol/grpc"
|
|
69
|
-
require "protocol/grpc/methods"
|
|
70
69
|
require "protocol/grpc/body/writable"
|
|
71
70
|
|
|
72
71
|
# Build request body
|
|
@@ -75,8 +74,8 @@ body.write(Hello::HelloRequest.new(name: "World"))
|
|
|
75
74
|
body.close_write
|
|
76
75
|
|
|
77
76
|
# Build headers
|
|
78
|
-
headers = Protocol::GRPC::
|
|
79
|
-
path = Protocol::GRPC::
|
|
77
|
+
headers = Protocol::GRPC::Metadata.build(timeout: 5.0)
|
|
78
|
+
path = Protocol::GRPC::Route.build("hello.Greeter", "SayHello")
|
|
80
79
|
|
|
81
80
|
# Create HTTP request
|
|
82
81
|
request = Protocol::HTTP::Request["POST", path, headers, body]
|
|
@@ -117,11 +116,11 @@ class MyMiddleware < Protocol::GRPC::Middleware
|
|
|
117
116
|
protected
|
|
118
117
|
|
|
119
118
|
def dispatch(request)
|
|
120
|
-
|
|
121
|
-
service_name, method_name = Protocol::GRPC::
|
|
119
|
+
# Parse the service and method from the path:
|
|
120
|
+
service_name, method_name = Protocol::GRPC::Route.parse(request.path)
|
|
122
121
|
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
# Handle the request using service_name and method_name.
|
|
123
|
+
# ...
|
|
125
124
|
end
|
|
126
125
|
end
|
|
127
126
|
```
|
|
@@ -144,4 +143,3 @@ call.deadline.exceeded? # => false
|
|
|
144
143
|
# Access peer information
|
|
145
144
|
call.peer # => Protocol::HTTP::Address
|
|
146
145
|
```
|
|
147
|
-
|
data/design.md
CHANGED
|
@@ -32,8 +32,8 @@ It does NOT include:
|
|
|
32
32
|
The protocol layer provides these core abstractions:
|
|
33
33
|
|
|
34
34
|
1. **Message Interface** - `Protocol::GRPC::Message` and `MessageHelpers`
|
|
35
|
-
2. **Path Handling** - `Protocol::GRPC::
|
|
36
|
-
3. **Metadata** - `Protocol::GRPC::Metadata` (extract
|
|
35
|
+
2. **Path Handling** - `Protocol::GRPC::Route` (build and parse request paths)
|
|
36
|
+
3. **Metadata** - `Protocol::GRPC::Metadata` (build request headers and extract or assign metadata)
|
|
37
37
|
4. **Body Framing** - `Protocol::GRPC::Body::Readable` and `Body::Writable`
|
|
38
38
|
5. **Status Codes** - `Protocol::GRPC::Status` constants
|
|
39
39
|
6. **Errors** - `Protocol::GRPC::Error` hierarchy
|
|
@@ -122,35 +122,29 @@ end
|
|
|
122
122
|
|
|
123
123
|
**Path of Least Resistance**: Google's `protobuf` gem already generates classes with `.decode(binary)` and `#to_proto` methods, so they work out of the box with no wrapper needed.
|
|
124
124
|
|
|
125
|
-
#### 2. `Protocol::GRPC::
|
|
125
|
+
#### 2. `Protocol::GRPC::Route` and `Protocol::GRPC::Metadata`
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
`Route` represents the service and method encoded in a gRPC request path. `Metadata` builds request headers and extracts application metadata:
|
|
128
128
|
|
|
129
129
|
```ruby
|
|
130
130
|
module Protocol
|
|
131
131
|
module GRPC
|
|
132
|
-
module
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# @parameter method [String] e.g., "SayHello"
|
|
136
|
-
# @returns [String] e.g., "/my_service.Greeter/SayHello"
|
|
137
|
-
def self.build_path(service, method)
|
|
138
|
-
"/#{service}/#{method}"
|
|
132
|
+
module Route
|
|
133
|
+
def self.parse(path)
|
|
134
|
+
# Return the service and method names.
|
|
139
135
|
end
|
|
140
136
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
# @returns [Tuple(String, String)] of service and method.
|
|
144
|
-
def self.parse_path(path)
|
|
145
|
-
parts = path.split("/")
|
|
146
|
-
[parts[1], parts[2]]
|
|
137
|
+
def self.build(service_name, method_name)
|
|
138
|
+
# Return the gRPC request path.
|
|
147
139
|
end
|
|
148
|
-
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
module Metadata
|
|
149
143
|
# Build gRPC request headers
|
|
150
144
|
# @parameter metadata [Hash] Custom metadata key-value pairs
|
|
151
145
|
# @parameter timeout [Numeric] Optional timeout in seconds
|
|
152
146
|
# @returns [Protocol::HTTP::Headers]
|
|
153
|
-
def self.
|
|
147
|
+
def self.build(metadata: {}, timeout: nil, content_type: "application/grpc+proto")
|
|
154
148
|
headers = Protocol::HTTP::Headers.new
|
|
155
149
|
headers["content-type"] = content_type
|
|
156
150
|
headers["te"] = "trailers"
|
|
@@ -171,7 +165,7 @@ module Protocol
|
|
|
171
165
|
# Extract metadata from gRPC headers
|
|
172
166
|
# @parameter headers [Protocol::HTTP::Headers]
|
|
173
167
|
# @returns [Hash] Metadata key-value pairs
|
|
174
|
-
def self.
|
|
168
|
+
def self.extract(headers)
|
|
175
169
|
metadata = {}
|
|
176
170
|
|
|
177
171
|
headers.each do |key, value|
|
|
@@ -553,7 +547,7 @@ module Protocol
|
|
|
553
547
|
# Extract metadata from request headers
|
|
554
548
|
# @returns [Hash] Custom metadata
|
|
555
549
|
def metadata
|
|
556
|
-
@metadata ||=
|
|
550
|
+
@metadata ||= Metadata.extract(@request.headers)
|
|
557
551
|
end
|
|
558
552
|
|
|
559
553
|
# Check if the deadline has expired
|
|
@@ -719,7 +713,7 @@ module Protocol
|
|
|
719
713
|
end
|
|
720
714
|
|
|
721
715
|
# Parse service and method from path
|
|
722
|
-
service_name, method_name =
|
|
716
|
+
service_name, method_name = Route.parse(request.path)
|
|
723
717
|
|
|
724
718
|
# Find handler
|
|
725
719
|
handler = @services[service_name]
|
|
@@ -836,13 +830,13 @@ body.write(MyService::HelloRequest.new(name: "World"))
|
|
|
836
830
|
body.close_write
|
|
837
831
|
|
|
838
832
|
# Build gRPC headers
|
|
839
|
-
headers = Protocol::GRPC::
|
|
833
|
+
headers = Protocol::GRPC::Metadata.build(
|
|
840
834
|
metadata: {"authorization" => "Bearer token123"},
|
|
841
835
|
timeout: 5.0
|
|
842
836
|
)
|
|
843
837
|
|
|
844
838
|
# Create HTTP request with gRPC path
|
|
845
|
-
path = Protocol::GRPC::
|
|
839
|
+
path = Protocol::GRPC::Route.build("my_service.Greeter", "SayHello")
|
|
846
840
|
|
|
847
841
|
request = Protocol::HTTP::Request[
|
|
848
842
|
"POST", path,
|
|
@@ -895,7 +889,7 @@ require "protocol/grpc"
|
|
|
895
889
|
# This would be inside a Rack/HTTP middleware/handler
|
|
896
890
|
def handle_grpc_request(http_request)
|
|
897
891
|
# Parse gRPC path
|
|
898
|
-
service, method = Protocol::GRPC::
|
|
892
|
+
service, method = Protocol::GRPC::Route.parse(http_request.path)
|
|
899
893
|
|
|
900
894
|
# Read input messages
|
|
901
895
|
input = Protocol::GRPC::Body::Readable.new(
|
|
@@ -1436,8 +1430,8 @@ This keeps dependencies minimal while providing great developer experience!
|
|
|
1436
1430
|
- Binary message support (no message_class = raw binary) (✅ Designed)
|
|
1437
1431
|
|
|
1438
1432
|
### Phase 2: Protocol Helpers
|
|
1439
|
-
- `Protocol::GRPC::
|
|
1440
|
-
- `Protocol::GRPC::Header`
|
|
1433
|
+
- `Protocol::GRPC::Route` (path parsing and building) (✅ Designed)
|
|
1434
|
+
- `Protocol::GRPC::Header` values (Status, Message, Timeout, Encoding) (✅ Designed)
|
|
1441
1435
|
- `Protocol::GRPC::HEADER_POLICY` for trailer support (✅ Designed)
|
|
1442
1436
|
- `Protocol::GRPC::Metadata` (status extraction, trailer helpers) (✅ Designed)
|
|
1443
1437
|
- `Protocol::GRPC::Call` context object (✅ Designed)
|
|
@@ -1644,4 +1638,3 @@ These map naturally to `Protocol::HTTP::Body::Writable` and `Readable`.
|
|
|
1644
1638
|
- [gRPC Protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)
|
|
1645
1639
|
- [Protocol::HTTP Design](https://socketry.github.io/protocol-http/guides/design-overview/)
|
|
1646
1640
|
- [gRPC over HTTP/2](https://grpc.io/docs/what-is-grpc/core-concepts/)
|
|
1647
|
-
|
data/lib/protocol/grpc/call.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Copyright, 2025, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "async/deadline"
|
|
7
|
-
require_relative "
|
|
7
|
+
require_relative "metadata"
|
|
8
8
|
|
|
9
9
|
module Protocol
|
|
10
10
|
module GRPC
|
|
@@ -46,7 +46,7 @@ module Protocol
|
|
|
46
46
|
# Extract metadata from request headers.
|
|
47
47
|
# @returns [Hash] Custom metadata key-value pairs
|
|
48
48
|
def metadata
|
|
49
|
-
@metadata ||=
|
|
49
|
+
@metadata ||= Metadata.extract(@request.headers)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# Get the timeout requested by the client.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
-
require_relative "
|
|
6
|
+
require_relative "route"
|
|
7
7
|
|
|
8
8
|
module Protocol
|
|
9
9
|
module GRPC
|
|
@@ -159,7 +159,7 @@ module Protocol
|
|
|
159
159
|
# @parameter method_name [String | Symbol] Method name in PascalCase (e.g., :SayHello)
|
|
160
160
|
# @returns [String] gRPC path with PascalCase method name
|
|
161
161
|
def path(method_name)
|
|
162
|
-
|
|
162
|
+
Route.build(@name, method_name.to_s)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
private
|
|
@@ -3,13 +3,67 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
+
require "base64"
|
|
7
|
+
|
|
6
8
|
require_relative "header"
|
|
7
9
|
require_relative "status"
|
|
8
10
|
|
|
9
11
|
module Protocol
|
|
10
12
|
module GRPC
|
|
11
|
-
#
|
|
13
|
+
# Provides operations for building and extracting gRPC metadata.
|
|
12
14
|
module Metadata
|
|
15
|
+
# Build gRPC request headers containing the given metadata.
|
|
16
|
+
# @parameter metadata [Hash] Custom metadata key-value pairs.
|
|
17
|
+
# @parameter timeout [Numeric | Nil] Optional timeout in seconds.
|
|
18
|
+
# @parameter content_type [String] The request content type.
|
|
19
|
+
# @returns [Protocol::HTTP::Headers] The constructed request headers.
|
|
20
|
+
def self.build(metadata: {}, timeout: nil, content_type: "application/grpc+proto")
|
|
21
|
+
headers = Protocol::HTTP::Headers.new(policy: Protocol::GRPC::HEADER_POLICY)
|
|
22
|
+
headers["content-type"] = content_type
|
|
23
|
+
headers["te"] = "trailers"
|
|
24
|
+
|
|
25
|
+
if timeout
|
|
26
|
+
# Coerced to proper format by header policy:
|
|
27
|
+
headers["grpc-timeout"] = timeout
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
metadata.each do |key, value|
|
|
31
|
+
# Binary headers end with -bin and are base64 encoded:
|
|
32
|
+
headers[key] = if key.end_with?("-bin")
|
|
33
|
+
Base64.strict_encode64(value)
|
|
34
|
+
else
|
|
35
|
+
value.to_s
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
headers
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Extract application metadata from gRPC headers.
|
|
43
|
+
# @parameter headers [Protocol::HTTP::Headers] The headers to inspect.
|
|
44
|
+
# @returns [Hash] The extracted metadata key-value pairs.
|
|
45
|
+
def self.extract(headers)
|
|
46
|
+
metadata = {}
|
|
47
|
+
|
|
48
|
+
headers.to_h.each do |key, value|
|
|
49
|
+
# Skip reserved headers:
|
|
50
|
+
next if key.start_with?("grpc-") || key == "content-type" || key == "te"
|
|
51
|
+
|
|
52
|
+
# Decode binary headers:
|
|
53
|
+
if key.end_with?("-bin")
|
|
54
|
+
if value.is_a?(String)
|
|
55
|
+
value = Base64.strict_decode64(value)
|
|
56
|
+
elsif value.is_a?(Array)
|
|
57
|
+
value = value.map{|item| Base64.strict_decode64(item)}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
metadata[key] = value
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
metadata
|
|
65
|
+
end
|
|
66
|
+
|
|
13
67
|
# Extract gRPC status from headers.
|
|
14
68
|
# Returns Status::UNKNOWN if status is not present.
|
|
15
69
|
#
|
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2025-2026, by Samuel Williams.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
require_relative "header/timeout"
|
|
6
|
+
require_relative "metadata"
|
|
7
|
+
require_relative "route"
|
|
10
8
|
|
|
11
9
|
module Protocol
|
|
12
10
|
module GRPC
|
|
@@ -16,16 +14,21 @@ module Protocol
|
|
|
16
14
|
# @parameter service [String] e.g., "my_service.Greeter"
|
|
17
15
|
# @parameter method [String] e.g., "SayHello"
|
|
18
16
|
# @returns [String] e.g., "/my_service.Greeter/SayHello"
|
|
17
|
+
# @deprecated Use {Route.build} instead.
|
|
19
18
|
def self.build_path(service, method)
|
|
20
|
-
"
|
|
19
|
+
Kernel.warn("`Protocol::GRPC::Methods.build_path` is deprecated; use `Protocol::GRPC::Route.build` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
20
|
+
|
|
21
|
+
Route.build(service, method)
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
# Parse service and method from gRPC path.
|
|
24
25
|
# @parameter path [String] e.g., "/my_service.Greeter/SayHello"
|
|
25
26
|
# @returns [Array(String | String)] [service, method]
|
|
27
|
+
# @deprecated Use {Route.parse} instead.
|
|
26
28
|
def self.parse_path(path)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
Kernel.warn("`Protocol::GRPC::Methods.parse_path` is deprecated; use `Protocol::GRPC::Route.parse` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
30
|
+
|
|
31
|
+
Route.parse(path)
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
# Build gRPC request headers.
|
|
@@ -33,53 +36,21 @@ module Protocol
|
|
|
33
36
|
# @parameter timeout [Numeric | Nil] Optional timeout in seconds
|
|
34
37
|
# @parameter content_type [String] Content type (default: "application/grpc+proto")
|
|
35
38
|
# @returns [Protocol::HTTP::Headers]
|
|
39
|
+
# @deprecated Use {Metadata.build} instead.
|
|
36
40
|
def self.build_headers(metadata: {}, timeout: nil, content_type: "application/grpc+proto")
|
|
37
|
-
|
|
38
|
-
headers["content-type"] = content_type
|
|
39
|
-
headers["te"] = "trailers"
|
|
41
|
+
Kernel.warn("`Protocol::GRPC::Methods.build_headers` is deprecated; use `Protocol::GRPC::Metadata.build` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
# Coerced to proper format by header policy:
|
|
43
|
-
headers["grpc-timeout"] = timeout
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
metadata.each do |key, value|
|
|
47
|
-
# Binary headers end with -bin and are base64 encoded:
|
|
48
|
-
headers[key] = if key.end_with?("-bin")
|
|
49
|
-
Base64.strict_encode64(value)
|
|
50
|
-
else
|
|
51
|
-
value.to_s
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
headers
|
|
43
|
+
Metadata.build(metadata: metadata, timeout: timeout, content_type: content_type)
|
|
56
44
|
end
|
|
57
45
|
|
|
58
46
|
# Extract metadata from gRPC headers.
|
|
59
47
|
# @parameter headers [Protocol::HTTP::Headers]
|
|
60
48
|
# @returns [Hash] Metadata key-value pairs
|
|
49
|
+
# @deprecated Use {Metadata.extract} instead.
|
|
61
50
|
def self.extract_metadata(headers)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
headers.to_h.each do |key, value|
|
|
65
|
-
# Skip reserved headers:
|
|
66
|
-
next if key.start_with?("grpc-") || key == "content-type" || key == "te"
|
|
67
|
-
|
|
68
|
-
# Decode binary headers:
|
|
69
|
-
if key.end_with?("-bin")
|
|
70
|
-
if value.is_a?(String)
|
|
71
|
-
value = Base64.strict_decode64(value)
|
|
72
|
-
elsif value.is_a?(Array)
|
|
73
|
-
value = value.map{|item| Base64.strict_decode64(item)}
|
|
74
|
-
end
|
|
75
|
-
else
|
|
76
|
-
value
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
metadata[key] = value
|
|
80
|
-
end
|
|
51
|
+
Kernel.warn("`Protocol::GRPC::Methods.extract_metadata` is deprecated; use `Protocol::GRPC::Metadata.extract` instead.", uplevel: 1, category: :deprecated) if $VERBOSE
|
|
81
52
|
|
|
82
|
-
|
|
53
|
+
Metadata.extract(headers)
|
|
83
54
|
end
|
|
84
55
|
|
|
85
56
|
# Format timeout for grpc-timeout header.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
module Protocol
|
|
7
|
+
module GRPC
|
|
8
|
+
# Provides operations for parsing and building gRPC request paths.
|
|
9
|
+
module Route
|
|
10
|
+
IDENTIFIER_PATTERN = "[A-Za-z][A-Za-z0-9_]*"
|
|
11
|
+
SERVICE_PATTERN = /\A#{IDENTIFIER_PATTERN}(?:\.#{IDENTIFIER_PATTERN})*\z/
|
|
12
|
+
METHOD_PATTERN = /\A#{IDENTIFIER_PATTERN}\z/
|
|
13
|
+
PATTERN = %r{\A/(#{IDENTIFIER_PATTERN}(?:\.#{IDENTIFIER_PATTERN})*)/(#{IDENTIFIER_PATTERN})\z}
|
|
14
|
+
private_constant :IDENTIFIER_PATTERN, :SERVICE_PATTERN, :METHOD_PATTERN, :PATTERN
|
|
15
|
+
|
|
16
|
+
# Parse a gRPC request path into its service and method names.
|
|
17
|
+
# @parameter path [String] The gRPC request path.
|
|
18
|
+
# @returns [Array(String)] The service and method names.
|
|
19
|
+
# @raises [ArgumentError] If the path does not contain valid protobuf service and method names.
|
|
20
|
+
def self.parse(path)
|
|
21
|
+
match = PATTERN.match(path) if path.is_a?(String)
|
|
22
|
+
|
|
23
|
+
unless match
|
|
24
|
+
raise ArgumentError, "Invalid gRPC route: #{path.inspect}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
[match[1], match[2]]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Build a gRPC request path from its service and method names.
|
|
31
|
+
# @parameter service_name [String] The fully qualified service name.
|
|
32
|
+
# @parameter method_name [String] The method name.
|
|
33
|
+
# @returns [String] The gRPC request path.
|
|
34
|
+
# @raises [ArgumentError] If either component is not a valid protobuf service or method name.
|
|
35
|
+
def self.build(service_name, method_name)
|
|
36
|
+
unless service_name.is_a?(String) && SERVICE_PATTERN.match?(service_name)
|
|
37
|
+
raise ArgumentError, "Invalid gRPC service name: #{service_name.inspect}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
unless method_name.is_a?(String) && METHOD_PATTERN.match?(method_name)
|
|
41
|
+
raise ArgumentError, "Invalid gRPC method name: #{method_name.inspect}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
"/#{service_name}/#{method_name}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/protocol/grpc.rb
CHANGED
|
@@ -7,9 +7,10 @@ require_relative "grpc/version"
|
|
|
7
7
|
|
|
8
8
|
require_relative "grpc/status"
|
|
9
9
|
require_relative "grpc/error"
|
|
10
|
-
require_relative "grpc/
|
|
10
|
+
require_relative "grpc/route"
|
|
11
11
|
require_relative "grpc/header"
|
|
12
12
|
require_relative "grpc/metadata"
|
|
13
|
+
require_relative "grpc/methods"
|
|
13
14
|
require_relative "grpc/call"
|
|
14
15
|
require_relative "grpc/body/readable"
|
|
15
16
|
require_relative "grpc/body/writable"
|
data/readme.md
CHANGED
|
@@ -28,6 +28,11 @@ Please see the [project documentation](https://socketry.github.io/protocol-grpc/
|
|
|
28
28
|
|
|
29
29
|
Please see the [project releases](https://socketry.github.io/protocol-grpc/releases/index) for all releases.
|
|
30
30
|
|
|
31
|
+
### v0.13.0
|
|
32
|
+
|
|
33
|
+
- Added `Protocol::GRPC::Route` for building and parsing gRPC request paths.
|
|
34
|
+
- Added `Protocol::GRPC::Metadata.build` and `Protocol::GRPC::Metadata.extract`, replacing the corresponding deprecated `Protocol::GRPC::Methods` helpers.
|
|
35
|
+
|
|
31
36
|
### v0.12.0
|
|
32
37
|
|
|
33
38
|
- Added `Protocol::GRPC::Call#timeout` to expose the client-supplied gRPC timeout in seconds.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.13.0
|
|
4
|
+
|
|
5
|
+
- Added `Protocol::GRPC::Route` for building and parsing gRPC request paths.
|
|
6
|
+
- Added `Protocol::GRPC::Metadata.build` and `Protocol::GRPC::Metadata.extract`, replacing the corresponding deprecated `Protocol::GRPC::Methods` helpers.
|
|
7
|
+
|
|
3
8
|
## v0.12.0
|
|
4
9
|
|
|
5
10
|
- Added `Protocol::GRPC::Call#timeout` to expose the client-supplied gRPC timeout in seconds.
|
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.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -118,6 +118,7 @@ files:
|
|
|
118
118
|
- lib/protocol/grpc/metadata.rb
|
|
119
119
|
- lib/protocol/grpc/methods.rb
|
|
120
120
|
- lib/protocol/grpc/middleware.rb
|
|
121
|
+
- lib/protocol/grpc/route.rb
|
|
121
122
|
- lib/protocol/grpc/status.rb
|
|
122
123
|
- lib/protocol/grpc/version.rb
|
|
123
124
|
- license.md
|
metadata.gz.sig
CHANGED
|
Binary file
|